Skip to content

fix(state): serialize WAL switch under the flock (fixes flaky concurrent open) - #65

Merged
gustavobertoi merged 1 commit into
mainfrom
nightly/fix-flaky-state-open
Jun 29, 2026
Merged

fix(state): serialize WAL switch under the flock (fixes flaky concurrent open)#65
gustavobertoi merged 1 commit into
mainfrom
nightly/fix-flaky-state-open

Conversation

@gustavobertoi

Copy link
Copy Markdown
Contributor

Problem

TestConcurrentOpenSerializes intermittently 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

Open called sqlDB.Ping() before taking the flock. Ping forces the first real connection, which applies the DSN _pragmas — including journal_mode=WAL. The WAL switch writes the DB header under a write lock, and a journal-mode change is not governed by busy_timeout, so concurrent first-opens racing the conversion get an immediate SQLITE_BUSY.

Fix

Move Ping inside the existing lock.WithLock block, next to migrate + 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=12 locally (was flaking ~1 in 8 on CI).

🤖 Generated with Claude Code

…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>
@gustavobertoi
gustavobertoi merged commit f6818a2 into main Jun 29, 2026
2 checks passed
@gustavobertoi
gustavobertoi deleted the nightly/fix-flaky-state-open branch June 29, 2026 19:10
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.

1 participant