fix(backup): persist last-success/error status; wall-clock-based schedule
BackupService tracked last-success/last-error as plain in-process fields and scheduled the daily backup via setInterval measured from process start — so any server restart (deploy/crash/OOM/reboot, routine under `restart: always`) silently reset the admin UI to "last successful backup: Never" and drifted the actual cadence, independent of whether backups were writing correctly to disk (they were — a real field incident at park-buzi showed 7 valid rotating backups on disk with the status stuck on "Never"). Persist last-success/error to new site_config columns (migration 0025) and add BackupService.isDue(), computed from the persisted timestamp instead of process uptime; server.ts now polls every 15 min and lets isDue() gate the actual run. No API/UI contract change. Claude-Session: https://claude.ai/code/session_01FWncR69HgGPuei1dLrW3cU
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
-- Last-success/last-error for the encrypted DB backup were previously tracked only as
|
||||
-- in-process fields on BackupService (never written to the DB) — so every server restart
|
||||
-- (deploy/crash/OOM/host reboot, all routine under `restart: always`) silently reset the admin
|
||||
-- UI's "last successful backup" to "Never", even with valid, correctly-rotating backups already
|
||||
-- on disk (2026-08-30 field incident, park-buzi). Four additive, nullable columns; null = no
|
||||
-- run recorded yet (or, for the error pair, no failure since the last success). See
|
||||
-- wiki/concepts/backup-recovery.md.
|
||||
ALTER TABLE `site_config` ADD `backup_last_success_at` text;--> statement-breakpoint
|
||||
ALTER TABLE `site_config` ADD `backup_last_result_json` text;--> statement-breakpoint
|
||||
ALTER TABLE `site_config` ADD `backup_last_error_at` text;--> statement-breakpoint
|
||||
ALTER TABLE `site_config` ADD `backup_last_error` text;
|
||||
Reference in New Issue
Block a user