fix(state): serialize WAL switch under the flock (fixes flaky concurrent open) - #65
Merged
Merged
Conversation
…y open) `TestConcurrentOpenSerializes` intermittently failed under `-race` with `ping state.db: database is locked (5) SQLITE_BUSY`. Root cause: `Open` called `sqlDB.Ping()` BEFORE taking the flock. Ping forces the first real connection, which applies the DSN `_pragma`s — including `journal_mode=WAL`. The WAL switch writes the DB header under a write lock, and that journal-mode change is NOT covered by `busy_timeout`, so concurrent first-opens racing the conversion get an immediate SQLITE_BUSY. Fix: move `Ping` inside the existing `lock.WithLock` block, alongside `migrate` + `ensureContext`, so the WAL conversion (a genuine mutation) is serialized across processes by the machine-global advisory lock — exactly the contract spec 08 already states for the mutating section. No behavior change for the single-open path. Verified with `-race -count=12`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
TestConcurrentOpenSerializesintermittently fails in CI under-race:ping state.db: database is locked (5) SQLITE_BUSY. (It just flaked PR #64; a re-run went green.)Root cause
OpencalledsqlDB.Ping()before taking the flock.Pingforces the first real connection, which applies the DSN_pragmas — includingjournal_mode=WAL. The WAL switch writes the DB header under a write lock, and a journal-mode change is not governed bybusy_timeout, so concurrent first-opens racing the conversion get an immediateSQLITE_BUSY.Fix
Move
Pinginside the existinglock.WithLockblock, next tomigrate+ensureContext, so the WAL conversion (a real mutation) is serialized across processes by the machine-global advisory lock — exactly the contract spec 08 already states for the mutating section. No change to the steady-state single-open path.Verified with
-race -count=12locally (was flaking ~1 in 8 on CI).🤖 Generated with Claude Code