fix(store): checkpoint WAL on close and startup to prevent orphan accumulation#387
Conversation
…umulation Add WAL checkpoint on store close and after WAL-mode enable at startup. This ensures graceful shutdown leaves a clean WAL, and crash recovery merges stale WAL on next open. Both use PASSIVE mode (non-blocking, no ftruncate). Best-effort — silently skip if concurrent reader holds a lock. Fixes DeusData#277
|
Thank you, @jjserenity! 🙏 This is a sharp, minimal fix for a genuinely nasty failure mode. You correctly identified that the existing Verified locally: build clean, all 3,622 tests pass. Merging via squash — authorship preserved. Closes #277, and this is a big one for the silent-corruption cluster tracked in #391. Thank you! 🙏 |
Fixes #277
Problem
codebase-memory-mcpprocesses can accumulate as orphan processes (e.g., from unclean stdio shutdown on Windows). Each orphan holds a SQLite WAL read lock, preventing checkpoint from ever landing. New index writes go to WAL but never merge into the main.db. The WAL grows unbounded, and queries return stale data.The existing
cbm_store_checkpoint()API uses safeSQLITE_CHECKPOINT_PASSIVEmode but is never called anywhere — zero call sites.Changes
Single file:
src/store/store.c(+10 lines)cbm_store_close(): Checkpoint WAL viasqlite3_wal_checkpoint_v2(..., PASSIVE)beforesqlite3_close_v2. This ensures graceful shutdown (SIGTERM,delete_project, normal exit) leaves a clean WAL that won't require recovery on next open.configure_pragmas(): AfterPRAGMA journal_mode=WAL, runPRAGMA wal_checkpoint(PASSIVE)to merge any stale WAL from a previous crash. Best-effort — silently skipped if another process holds a lock (SQLITE_BUSY).Rationale
ftruncate()s, compatible with PR fix(store): use PASSIVE checkpoint to avoid file-shrink under concurrent readers #316's existing choice.delete_project→ checkpoint runs insidecbm_store_closebefore file unlink, so WAL is merged before deletion.Tested
-Wall -Wextra -Werror)