Skip to content

Preserve session history through lock contention and damaged writes - #127

Open
iPeluwa wants to merge 2 commits into
iamnotstatic:mainfrom
iPeluwa:fix/session-storage-recovery
Open

iPeluwa wants to merge 2 commits into
iamnotstatic:mainfrom
iPeluwa:fix/session-storage-recovery

Conversation

@iPeluwa

@iPeluwa iPeluwa commented Oct 21, 2026 •

Copy link
Copy Markdown

Session history could disappear after a killed hook left a stale lock, concurrent writers shared one temporary file, or a damaged database was reset to empty. This groups #123 with the additional partial-record recovery found locally.

  • Recover abandoned locks, including directories with no PID. Keep live holders even when their locks are old.
  • Serialize dead-lock removal with sessions.lock.break and recheck the holder after taking that gate, so two removers cannot delete a replacement live lock.
  • Wait up to roughly two seconds for contention, then report a busy database instead of writing without a lock.
  • Write through a unique temporary file and rename atomically.
  • Salvage complete session records from truncated or spliced JSON, keeping the later complete copy of duplicate IDs and rejecting incomplete records.
  • Keep reads read-only. Before a locked repair replaces damaged data, retain the original bytes in a uniquely named .corrupt backup; a failed backup stops the write.

Validation: the complete local suite passes 161/161. Storage regressions cover stale/live locks, timeout, concurrent writers preserving all records, truncation/splicing and backup preservation, plus a held breaker gate, deterministic replacement of the dead holder before the gated recheck, and eight synchronized writers recovering one dead lock. The new gate/recheck regressions fail against the previous PR head.

Recovery cannot reconstruct incomplete records; their original bytes remain in the backup. Breaker gates are held only during synchronous lock repair; contention fails closed.

Combined validation: all three revised branches merge cleanly in the order below and pass 192/192 local tests together.

Merge order: 1. #127 (this PR) → 2. #129 (delivery) → 3. #128 (ZCode). This replaces the closed #123. No migration or data rewrite is performed on healthy reads.

@iamnotstatic

Copy link
Copy Markdown
Owner

Race is fixed, 0 of 60 rounds with 8 processes, nice. One thing left: a lock whose pid got reused (common after a reboot) or a leftover sessions.lock.break never clears now, so every write throws "busy" forever, and vibe __wrap exits 1 with no endcard. Treating a live pid as stale once the lock is over 10 minutes old, and removing a break dir older than LOCK_STALE_MS, fixed both for me and your tests still pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants