Skip to main content

Scheduled & background tasks

Long-running work uses Django's native task framework with a database backend, picked up by the worker container (python manage.py db_worker). Time-driven work (there is no built-in scheduler) runs through host cron.

Background tasks

Tasks are started on demand (for example from the admin panel) and executed by the worker. Every run produces a result row.

StatusMeaning
READYQueued, waiting for a worker
RUNNINGCurrently being processed
SUCCESSFULCompleted without errors
FAILEDCompleted with an error
Where to watch results

Task results are shown read-only in the admin under Administration → System → Task status, scoped to the current institute.

Scheduled (cron) jobs

Cron runs on the host and calls Django management commands inside the server container via docker compose exec.

Cron nameScheduleCommandPurpose
ses-cleanup-remote-seatsdaily 03:00cleanup_remote_seatsRelease expired remote-app seats
ses-prewarm-due-examsevery 5 minprewarm_due_examsProvision remote-app seats before exams
ses-import-ems-examsevery 5 minimport_ems_exams --scheduledImport new/changed external exams
ses-cleanup-sso-sessionsdaily 04:00ses_cleanup_sso_sessionsRemove expired SSO sessions
ses-cleanup-db-task-resultsdaily 04:05prune_db_task_resultsRemove finished task results

Example cron entry (SSO cleanup):

0 4 * * * cd /opt/ses && docker compose exec ses-server python manage.py ses_cleanup_sso_sessions --delete-orphan-users >> /var/log/ses-sso-cleanup.log 2>&1

Cleaning up task results

Finished results are pruned on a schedule to avoid database growth:

# Preview for 14-day-old successes, 45-day-old failures (no changes)
python manage.py prune_db_task_results --min-age-days 14 --failed-min-age-days 45 --dry-run
Why cron and not a scheduler

Django's task framework has a worker for the queue but no built-in scheduler, so time-based work is scheduled with host cron.

Removing expired SSO sessions

SSO sessions expire over time. To limit database growth and stay compliant with data retention, schedule a cleanup. The command iterates over all tenant schemas automatically.

# Preview what would be deleted (no changes)
python manage.py cleanup_expired_sso_sessions --dry-run

# Delete expired sessions (default: older than 30 days)
python manage.py cleanup_expired_sso_sessions

# Also remove orphaned user accounts
python manage.py cleanup_expired_sso_sessions --delete-orphan-users
OptionDefaultPurpose
--dry-runoffShow what would be deleted, change nothing
--delete-orphan-usersoffAlso remove users with no usable password and no sessions
--max-age-days N30Only delete sessions older than N days

Schedule it daily via cron:

0 3 * * * cd /opt/ses && docker compose exec ses-server python manage.py cleanup_expired_sso_sessions --delete-orphan-users >> /var/log/ses-sso-cleanup.log 2>&1
Never touch staff accounts

--delete-orphan-users only removes accounts with no usable password and no remaining SSO sessions, so superusers and staff are never removed.