Scheduler: the upload scrub rereads and rehashes 25 files every five minutes however recently they were checked #1118
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#1118
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
src/postulo/notifications/management/commands/send_due_reminders.py:230callsscrub.verify_uploads(limit=SCRUB_SLICE)on every scheduler pass;SCRUB_SLICE = 25(line 32) and the pass runs every 300 s by default (line 127), 288 passes a day.src/postulo/documents/scrub.py:47-69takes the 25 uploads with the oldestverified_at(line 55, no age filter), reads each file whole throughintegrity.damage_of(documents/integrity.py:176-196, a SHA-256 over the file), and writesdamage,verified_atandsizewith oneUPDATEper row (line 62). The selection is "least recently checked first" with no "and not checked in the last N days", so on an instance with fewer than 7,200 uploads every file is hashed several times a day: with 100 uploads, each one is read 72 times a day. Uploads are capped at 20 MB (documents/forms.py:29, per #663), so the worst case is 500 MB read per pass.#663 (closed) asked for "a fixed number of rows each time, oldest-checked first"; it did not ask for a minimum age, so this is a refinement of that design, not a reversal. No open issue covers it (searched "scrub", "verify uploads", "media sweep").
What would change
In
verify_uploads, whenlimitis given (the scheduled slice), select only rows withverified_atnull or older than a new settingPOSTULO_SCRUB_EVERY_DAYS(default 7):rows.filter(Q(verified_at__isnull=True) | Q(verified_at__lt=now - dt.timedelta(days=…)))manage.py verify_media(nolimit) keeps reading everything. The slice size stays 25, which still reaches a backlog of 7,200 files a day. The wiki page that describes the scrub gains the setting. An index onverified_at(candidate Q7) makes the filter cheap; both can be one PR.No library: one queryset filter and one setting.
What it saves or protects
medium: 7,200 file reads and hashes and 7,200 single-row UPDATEs a day become one read per upload per chosen interval (for 100 uploads checked weekly, about 14 a day)
Accessibility
none
Decisions
Found by the efficiency and reliability audit of 2026-10-30 (finding B2; index postulo/postulo#1108). Checked against
mainatdaee30b15(2026-10-30).