fix(db): WAL truncate at parked barriers ONLY — the timer-path truncate loses the race it was assumed to lose (#1336)
A truncate checkpoint started against an ACTIVE writer wins the lock and then blocks that writer for its entire backfill; after the edge-index recreate's multi-GB single-transaction burst that exceeds the writer's 5s busy_timeout and fails the index with 'database is locked' (§7a.2 record run, EXIT=1 at kernel scale — the small mid-resolution truncates folded in ms and masked the hazard). Barrier truncates (backpressure/foldNow) are collision-free by construction: the writer is awaiting the valve. Dubbo gate: exit 0, peak 81MB (barrier folds carry containment), dump byte-identical. Valve + sizing suites 27/27. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
ca88d3bd15
commit
2adc7f60c0
+8
-10
@@ -263,16 +263,14 @@ export class WalCheckpointValve {
|
|||||||
// SQLite reports log = checkpointed = -1, which is harmless here.
|
// SQLite reports log = checkpointed = -1, which is harmless here.
|
||||||
if (res && res.busy === 0 && res.log === res.checkpointed) {
|
if (res && res.busy === 0 && res.log === res.checkpointed) {
|
||||||
this.sizeAtLastFullBackfill = this.db.getWalSizeBytes();
|
this.sizeAtLastFullBackfill = this.db.getWalSizeBytes();
|
||||||
// Opportunistic file chop while everything is folded: best-effort —
|
// NO truncate here. A truncate checkpoint that starts against an
|
||||||
// an active writer/reader turns it into a busy no-op, and the
|
// ACTIVE writer wins the lock race and then blocks that writer for
|
||||||
// barrier-path truncate (backpressure file cap) remains the
|
// its entire backfill — after a multi-GB single-transaction burst
|
||||||
// deterministic bound.
|
// (edge-index recreate) that exceeds the writer's 5s busy_timeout
|
||||||
if (this.db.getWalSizeBytes() > this.softBytes * 2) {
|
// and fails the index with "database is locked" (§7a.2 record run).
|
||||||
return this.db.checkpointWalTruncate().then((t) => {
|
// The file chop happens exclusively at parked barriers
|
||||||
if (t) this.log(`timer truncate: busy=${t.busy} wal=${this.mb(this.db.getWalSizeBytes())}`);
|
// (backpressure/foldNow), where the writer is awaiting us by
|
||||||
this.sizeAtLastFullBackfill = this.db.getWalSizeBytes();
|
// construction and cannot collide.
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => { /* best-effort */ })
|
.catch(() => { /* best-effort */ })
|
||||||
|
|||||||
Reference in New Issue
Block a user