Backups: a backup killed mid-way blocks scheduled backups for 6 hours and *Back up now* for 24 #1131
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#1131
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
core/backups.py:53-55setsLOCK_SECONDS = 6 * 3600, andtake(core/backups.py:245-261) holdsLOCK_KEYwithcache.addfor that long, releasing it in afinally. A worker killed mid-backup (container restart, out-of-memory killer, deploy) never runs thefinally, so:run_scheduled(core/backups.py:401-413) raisesBusyfor up to 6 hours and records "Another backup was already running." A daily slot that falls inside those hours is lost.core/views_backups.py:94-100_a_backup_is_runningalso refuses while anybackuperrand isWAITINGorWORKINGand was created in the last 24 hours. The killed errand staysWORKINGuntilerrands.fail_interrupted(core/errands.py:193, defaulthours=24, called fromsend_due_reminders.py:214) marks it failed after 24 hours. Until then the button says "A backup is already running. Wait for it to finish." (core/views_backups.py:173-175), with no way to clear it from the interface.What would change
A short lease that the running backup renews, rather than one long enough for the slowest backup:
LOCK_SECONDSof about 10 minutes, renewed by the backup as it goes:core/backup.pywrite_backupwalks the media and plugin trees in_add_tree(called at lines 555-557), which is the natural place to call arenewevery minute or every N files. With R2's lease table that isUPDATE ... WHERE key AND token; with the cache as today it iscache.touch(LOCK_KEY, LOCK_SECONDS)._a_backup_is_runningstops trusting the errand row on its own: it asks the lease, and treats abackuperrand as running only while the lease is held. A dead backup then frees both the schedule and the button within one lease period.fail_interruptedfor thebackupkind uses the same short window, so the dead errand's page says it was interrupted within minutes, not a day.What it saves or protects
small: a worker restart during a backup no longer costs the next scheduled backup or a day of Back up now
Accessibility
none
Decisions
renew; it can land alone withcache.touchif R2 waits.Found by the efficiency and reliability audit of 2026-10-30 (finding R3; index postulo/postulo#1108). Checked against
mainatdaee30b15(2026-10-30).