feat(recovery): the fold-checkpoint bound — crash folds (checkpoint, head], never the whole log twice
The fold checkpoint (_system/fold-checkpoint.json) is stamped strictly after a canonical-sync barrier over every live entity touched since the last stamp (syncEntityCanonical: ids → canonical paths → fsync; an absent file fsyncs its parent directory so deletes are as durable as writes). An unclean open under log authority now folds only (checkpoint, head]; the chain bootstraps at an empty brain's adoption (three-phase hooks around adoptLogAuthority) or at a brain's first whole-log fold — existing brains converge at their first crash with zero regression. Rollback restores sync immediately; abort paths feed the barrier; a failed barrier retains the old bound (bigger fold later, never a lost write). Five structural pins including boundedness itself. Also: the production-shaped write-flow gate leg (mixed traffic racing flushes, crash mid-traffic, every ack survives — from a consumer-reported gate miss), and two release-ceremony cures (tag-first push so the publish never queues behind the release commit's CI run; raw-curl npmjs shasum probe with propagation grace instead of a one-shot false divergence).
This commit is contained in:
parent
cbe34d115e
commit
ff43de1ada
8 changed files with 695 additions and 12 deletions
|
|
@ -799,6 +799,7 @@ export class FileSystemStorage extends BaseStorage {
|
|||
|
||||
for (const objectPath of paths) {
|
||||
const fullPath = path.join(this.rootDir, objectPath)
|
||||
let synced = false
|
||||
for (const candidate of [`${fullPath}.gz`, fullPath]) {
|
||||
let handle: any
|
||||
try {
|
||||
|
|
@ -813,8 +814,14 @@ export class FileSystemStorage extends BaseStorage {
|
|||
await handle.close()
|
||||
}
|
||||
parentDirs.add(path.dirname(fullPath))
|
||||
synced = true
|
||||
break
|
||||
}
|
||||
// An absent path is a state too: fsync the parent directory so a
|
||||
// completed unlink is durable (a delete must survive power loss as
|
||||
// surely as a write — otherwise a bounded log fold could let a
|
||||
// tombstoned record resurrect from a lost directory update).
|
||||
if (!synced) parentDirs.add(path.dirname(fullPath))
|
||||
}
|
||||
|
||||
for (const dir of parentDirs) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue