Fix StateManager deadlock with explicit BEGIN IMMEDIATE + retry

with conn: context manager in Python sqlite3 doesn't respect busy_timeout
for the implicit BEGIN; under concurrent subprocess writes the transaction
would fail immediately. Replace with explicit BEGIN IMMEDIATE + retry loop
(6 attempts, 0.5s back-off) to handle WAL write contention.
This commit is contained in:
Cobra
2026-04-07 12:23:38 -04:00
parent a8b81f38c9
commit 7f58f1cab3
+21 -4
View File
@@ -250,12 +250,29 @@ class StateManager:
return
conn = self._get_write_conn()
try:
with conn:
for attempt in range(6):
try:
conn.execute("BEGIN IMMEDIATE")
for sql, params in batch:
conn.execute(sql, params)
except Exception:
logger.exception("StateManager flush failed (%d ops)", len(batch))
conn.execute("COMMIT")
return
except sqlite3.OperationalError as e:
try:
conn.execute("ROLLBACK")
except Exception:
pass
if attempt < 5:
time.sleep(0.5 * (attempt + 1))
else:
logger.error("StateManager flush failed after 6 attempts (%d ops): %s", len(batch), e)
except Exception:
try:
conn.execute("ROLLBACK")
except Exception:
pass
logger.exception("StateManager flush failed (%d ops)", len(batch))
return
def _writer_loop(self) -> None:
"""Background loop: flush write queue every FLUSH_INTERVAL seconds."""