fix(state): a busy write lock no longer loses the write that hit a corrupt FTS index
When a canonical write trips a corrupt FTS index, SessionDB detaches the derived indexes (breadcrumb + trigger drop) and retries the write. The detach ran one BEGIN IMMEDIATE on the writer connection, whose busy timeout is only 1 s, and gave up on "database is locked" — so the canonical write escaped as "database disk image is malformed". The usual lock holder is a sibling writer (gateway + TUI) detaching the same index, so under load the second writer's turn was lost. The detach now waits out lock contention on the caller's write budget with the same jittered retry as _execute_write (default _WRITE_PATIENCE_S for the search fail-open callers). Repro: a second process takes BEGIN IMMEDIATE the instant the corruption error surfaces and holds it 2.5 s. Base: append raises after 1.02 s (3/3). Fixed: the row lands after the holder releases, FTS detached (3/3). Found by the E2E sqlite torture chamber (fts_corruption_fail_open) at load ~200.
This commit is contained in:
@@ -1078,7 +1078,7 @@ class SessionDB(
|
||||
self._raise_if_db_replaced()
|
||||
# Corrupt FTS shadow tables fail every write via the sync triggers while canonical
|
||||
# rows are intact: detach the derived indexes atomically and retry (never rebuild here).
|
||||
if self._enter_fts_fail_open(exc):
|
||||
if self._enter_fts_fail_open(exc, deadline=deadline, patience_s=patience_s):
|
||||
continue
|
||||
# What survives both checks is structural damage: quarantine.
|
||||
if self._is_structural_corruption_error(exc):
|
||||
|
||||
Reference in New Issue
Block a user