fix: guard the integrity sweep against wiping the library on a dead mount
The sweep stats every track path and marks unreadable files missing, with no
check that /music is mounted. An unmounted or misbehaving bind would fail
every stat and mark the entire library missing in one pass; the ratio is only
recoverable by a full rescan.
Three guards, cheapest first:
- liveness: probe a sample of existing track paths before doing anything;
abort if none are readable
- ratio: abort mid-sweep if the missing fraction crosses a threshold,
leaving already-marked rows alone rather than rolling back a partial pass
- progress: keyset pagination over id with the cursor persisted in
integrity_sweep_state, so a sweep aborted or restarted mid-run resumes
instead of re-walking from the top and re-marking
The repair-corrupted-metadata script shares the same failure mode and gets
the same abort path.
REVIEW-2026-07-30.md secondary finding: integrity sweep has no mount check.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -113,9 +113,13 @@ async function initWorker() {
|
||||
console.log('[Integrity] Starting integrity sweep');
|
||||
const integrityService = new IntegrityService(pgPool, queue);
|
||||
const summary = await integrityService.runSweep();
|
||||
console.log(
|
||||
`[Integrity] Sweep complete: detected=${summary.detected} fixed=${summary.fixed} needsReview=${summary.needsReview}`
|
||||
);
|
||||
if (summary.aborted) {
|
||||
console.error(`[Integrity] Sweep ABORTED by safety guard: ${summary.abortReason}`);
|
||||
} else {
|
||||
console.log(
|
||||
`[Integrity] Sweep complete: detected=${summary.detected} fixed=${summary.fixed} needsReview=${summary.needsReview}`
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'cleanup_sweep': {
|
||||
|
||||
Reference in New Issue
Block a user