Scheduler: finished background task rows are kept for ever #1121
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#1121
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What exists today
django_tasks_db0.13.0 shipsmanage.py prune_db_task_results(.venv/Lib/site-packages/django_tasks_db/management/commands/prune_db_task_results.py;--min-age-daysdefault 14,--failed-min-age-days,--queue-namedefaultdefault,*for all). Nothing insrc/postulocalls it (grep forprune_db_task_resultsfinds nothing), the scheduler pass does not do the equivalent, and the wiki does not tell operators to run it.Every task enqueued (
core/errands.py:106perform_errand.enqueue,core/backups.py:279/core/offsite_queue.py:25) leaves aDBTaskResultrow withargs_kwargs,return_value,worker_idsand, when it failed,exception_class_pathand the wholetraceback(django_tasks_db/models.py:152-169). The only reader is the staff overview's count ofREADYrows (core/server_views.py:201-205).The scheduler already forgets the errand rows these tasks belong to after seven days (
core/errands.py:211-221, called fromsend_due_reminders.py:215), so a task result outlives the errand that gave it meaning.What would change
In the scheduler pass, beside
errands.forget_old(), delete finished task results older than the same seven days, for every queue:DBTaskResult.objects.finished().filter(finished_at__lte=cutoff).delete()which is exactly the query upstream's command runs (lines 111-122), or
call_command("prune_db_task_results", queue_name="*", min_age_days=7). Calling the upstream command keeps the library's definition of "finished"; the direct query avoids its logging setup. Either is a few lines; the house rule (library first) favours the command or itsfinished()manager method rather than a hand-written status list. Add the count to the pass'sreapedtotal. A test: a successful and a failed result eight days old are gone after a pass, aREADYone and a fresh one stay.What it saves or protects
small: the
django_tasks_dbresult table stops growing by one row per errand, archive copy and webhook task for the life of the instance; failed rows carry a full traceback eachAccessibility
none
Decisions
Found by the efficiency and reliability audit of 2026-10-30 (finding B5; index postulo/postulo#1108). Checked against
mainatdaee30b15(2026-10-30).