Harden fusion.db against recurring corruption
Root cause: node:sqlite SIGSEGVs inside pager_write leave the B-tree malformed in a way that still opens but fails integrity checks; large operational-log tables widen the write window where the crash strikes. - backup: verify every copy with PRAGMA quick_check, quarantine corrupt copies as *.corrupt, and never rotate out the last verified-good backup - db: add Database.recoverIfCorrupt() startup guard (wired into TaskStore.init, disk-backed only, opt out via FUSION_DISABLE_DB_AUTORECOVER) that rebuilds a malformed db via sqlite3 .recover, preserving the corrupt original; also fixes the latent `.recover main` invalid-option bug that made recoverDatabase() always fail - db: drop lost_and_found* scratch tables on init; add pruneOperationalLogs() - settings: add operationalLogRetentionDays (default 30, 0 = off) and prune activityLog/agentLogEntries/runAuditEvents/agentHeartbeats during maintenance - dashboard: expose retention in Settings -> Backups -> Database Maintenance Tests: backup 59/59, db 135/135 (incl. real corrupt->recover->reopen), self-healing cleanup/corruption 10/10, settings 77/77, SettingsModal 460/460. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1626,6 +1626,22 @@ export class SelfHealingManager {
|
||||
log.log(`Maintenance batch 1 step "cleanup-old-mail" succeeded — messagesDeleted=${messagesDeleted}`);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "prune-operational-logs",
|
||||
fn: async () => {
|
||||
const days = Number(settings.operationalLogRetentionDays ?? 0);
|
||||
if (!Number.isFinite(days) || days <= 0) {
|
||||
log.log("Maintenance batch 1 step \"prune-operational-logs\" skipped — operationalLogRetentionDays is not enabled");
|
||||
return;
|
||||
}
|
||||
const { deletedTotal, deletedByTable } = this.store.pruneOperationalLogs(days * 86_400_000);
|
||||
const detail = Object.entries(deletedByTable)
|
||||
.filter(([, n]) => n > 0)
|
||||
.map(([t, n]) => `${t}=${n}`)
|
||||
.join(" ");
|
||||
log.log(`Maintenance batch 1 step "prune-operational-logs" succeeded — deleted=${deletedTotal}${detail ? ` (${detail})` : ""}`);
|
||||
},
|
||||
},
|
||||
{ name: "checkpoint-wal", fn: () => Promise.resolve(this.checkpointWal()) },
|
||||
{ name: "enforce-worktree-cap", fn: () => this.enforceWorktreeCap() },
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user