fix(kanban): skip redundant WAL pragma on already-WAL connections

apply_wal_with_fallback() issued PRAGMA journal_mode=WAL on every call,
including connections to DBs already in WAL mode. This triggered the WAL
init code path, causing SQLite to acquire EXCLUSIVE, checkpoint, and unlink
kanban.db-{wal,shm}. Other open connections received (deleted) FDs and
raised sqlite3.OperationalError: disk I/O error.

Add a cheap read probe (PRAGMA journal_mode, no flock/checkpoint/unlink)
before the set-pragma path. If already wal, return early. The set-pragma
and DELETE fallback paths are unchanged.

Closes #31158. Addresses root cause that PRs #32226 and #32322 attempted
via connection-sharing/caching approaches.
This commit is contained in:
Stephen Chin 2026-05-25 23:26:17 -07:00 committed by kshitij
parent ffdc937c18
commit dc98314fbd
3 changed files with 250 additions and 14 deletions

View file

@ -170,6 +170,15 @@ def apply_wal_with_fallback(
Never downgrades to DELETE if the on-disk DB header reports WAL see _on_disk_journal_mode.
"""
# Read-only probe — no flock, no checkpoint, no WAL/SHM unlink.
# Skipping the set-pragma prevents WAL-init from unlinking files other connections hold open.
try:
current_mode = conn.execute("PRAGMA journal_mode").fetchone()
if current_mode and current_mode[0] == "wal":
return "wal"
except sqlite3.OperationalError:
pass
try:
conn.execute("PRAGMA journal_mode=WAL")
return "wal"