""" Registriert den Retention-Cleanup als Periodic Task in django_celery_beat. Standardplan: täglich um 03:15 Uhr (kollidiert nicht mit dem Backup-Service, der i.d.R. um 03:00 läuft, und liegt in der Wartungsphase). Die Zeitzone richtet sich nach `settings.CELERY_TIMEZONE` bzw. `TIME_ZONE`. """ from __future__ import annotations from django.db import migrations CRON_HOUR = "3" CRON_MINUTE = "15" TASK_NAME = "Retention-Cleanup: abgelaufene Jobs löschen" TASK_DOTTED = "mailmerge.cleanup_expired_jobs" def create_periodic_task(apps, schema_editor): CrontabSchedule = apps.get_model("django_celery_beat", "CrontabSchedule") PeriodicTask = apps.get_model("django_celery_beat", "PeriodicTask") from django.conf import settings schedule, _ = CrontabSchedule.objects.get_or_create( minute=CRON_MINUTE, hour=CRON_HOUR, day_of_week="*", day_of_month="*", month_of_year="*", timezone=getattr(settings, "CELERY_TIMEZONE", settings.TIME_ZONE), ) PeriodicTask.objects.update_or_create( name=TASK_NAME, defaults={ "crontab": schedule, "task": TASK_DOTTED, "enabled": True, "description": ( "Entfernt MailMergeJobs im Status DONE/FAILED, deren " "finished_at älter als JOB_RETENTION_DAYS ist. " "Inkl. recipients_csv und result_pdf auf dem Storage." ), }, ) def remove_periodic_task(apps, schema_editor): PeriodicTask = apps.get_model("django_celery_beat", "PeriodicTask") PeriodicTask.objects.filter(name=TASK_NAME).delete() class Migration(migrations.Migration): """Achtung: Wir definieren KEINE konkrete Migrationsabhängigkeit zu django_celery_beat, weil dessen letzte Migration je Paketversion unterschiedlich heißt. `run_before`/`dependencies` mit `("__latest__")` gibt es nicht. Stattdessen verlassen wir uns auf die Reihenfolge: django_celery_beat steht in INSTALLED_APPS und wird mit `migrate` immer vorab gewandert (Django sortiert nach Abhängigkeiten der App-Initials). Beim Build wird `migrate` ohnehin sequentiell ausgeführt, daher läuft diese Migration zuverlässig nach allen django_celery_beat-Migrationen, sobald `mailmerge.0001_initial` durch ist. """ dependencies = [ ("mailmerge", "0001_initial"), ] operations = [ migrations.RunPython(create_periodic_task, remove_periodic_task), ]