fixed worker entrypoint and implemented live logs with manual job scheduling

This commit is contained in:
nvrl committed 2026-02-19 18:15:13 +01:00
1 parent ef93ea41ca
commit 31144e4704
5 files changed
+88 -27

No files matched your search

+34 -9
View File
@@ -11,6 +11,7 @@ class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument('--output', type=str, help='Specific output path for the backup file')
parser.add_argument('--retention', type=int, default=7, help='Number of days to keep old backups')
parser.add_argument('--full', action='store_true', help='Create a full archive including media')
def handle(self, *args, **options):
db_conf = settings.DATABASES['default']
@@ -22,29 +23,53 @@ class Command(BaseCommand):
backup_dir = os.path.join(settings.BASE_DIR, 'backups')
os.makedirs(backup_dir, exist_ok=True)
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
# 1. Database Backup
if options['output']:
backup_path = options['output']
db_backup_path = options['output']
else:
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
backup_path = os.path.join(backup_dir, f'db_backup_{timestamp}.sqlite3')
db_backup_path = os.path.join(backup_dir, f'db_backup_{timestamp}.sqlite3')
self.stdout.write(f"Starting backup of {db_path}...")
self.stdout.write(f"Cloning database {db_path}...")
try:
# Use SQLite's online backup API for a consistent copy
src = sqlite3.connect(db_path)
dst = sqlite3.connect(backup_path)
dst = sqlite3.connect(db_backup_path)
with dst:
src.backup(dst)
dst.close()
src.close()
self.stdout.write(self.style.SUCCESS(f"Successfully backed up database to {backup_path}"))
self.stdout.write(self.style.SUCCESS(f"DB backup created: {db_backup_path}"))
except Exception as e:
self.stdout.write(self.style.ERROR(f"Database backup failed: {e}"))
self.stdout.write(self.style.ERROR(f"DB backup failed: {e}"))
return
# 2. Cleanup Old Backups
# 2. Full Archive (Optional)
if options['full']:
import tarfile
archive_name = f"full_backup_{timestamp}.tar.gz"
archive_path = os.path.join(backup_dir, archive_name)
self.stdout.write(f"Creating full archive at {archive_path}...")
try:
with tarfile.open(archive_path, "w:gz") as tar:
# Add database
tar.add(db_backup_path, arcname="db.sqlite3")
# Add media
media_dir = str(settings.MEDIA_ROOT)
if os.path.exists(media_dir):
tar.add(media_dir, arcname="media")
# Remove the raw sqlite backup after bundling it into the archive
if not options['output']:
os.remove(db_backup_path)
self.stdout.write(self.style.SUCCESS(f"Full archive created successfully."))
except Exception as e:
self.stdout.write(self.style.ERROR(f"Archive creation failed: {e}"))
# 3. Cleanup Old Backups
retention_days = options['retention']
cutoff = datetime.now() - timedelta(days=retention_days)
+10 -2
View File
@@ -39,10 +39,18 @@ class Command(BaseCommand):
self.stdout.write(f"Executing Job: {job.get_name_display()}...")
job.status = 'running'
job.last_run = timezone.now()
job.last_output = "" # Reset output for new run
job.save()
# Capture management command output
out = StringIO()
class LiveStream(StringIO):
def write(self, s):
super().write(s)
# Periodically update the DB with current output
job.last_output = self.getvalue()
job.save(update_fields=['last_output'])
out = LiveStream()
error = ""
try:
@@ -51,7 +59,7 @@ class Command(BaseCommand):
elif job.name == 'cleanup_duplicates':
call_command('cleanup_duplicates', stdout=out)
elif job.name == 'backup_db':
call_command('backup_db', stdout=out)
call_command('backup_db', '--full', stdout=out)
elif job.name == 'seed_legacy':
call_command('seed_legacy_flavors', stdout=out)
+11 -5
View File
@@ -912,13 +912,19 @@ class AdminViewSet(viewsets.ViewSet):
try:
job = Job.objects.get(pk=pk)
interval = request.data.get('interval_hours')
next_run = request.data.get('next_run')
if interval is not None:
job.interval_hours = int(interval)
# If we just enabled it, set next_run
if job.interval_hours > 0 and not job.next_run:
from django.utils import timezone
job.next_run = timezone.now()
job.save()
if next_run is not None:
from django.utils.dateparse import parse_datetime
job.next_run = parse_datetime(next_run)
elif interval is not None and job.interval_hours > 0 and not job.next_run:
from django.utils import timezone
job.next_run = timezone.now()
job.save()
return Response(JobSerializer(job).data)
except Job.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)