fix(kanban): fail closed and serialize sqlite writes - #31740
fix(kanban): fail closed and serialize sqlite writes#31740usmch1134-droid wants to merge 2 commits into
Conversation
teknium1
left a comment
There was a problem hiding this comment.
Thanks for the focused SQLite-hardening investigation. The WAL-fallback half is already on current main, but this branch cannot be salvaged as a direct cherry-pick.
Problems
hermes_cli/kanban_db.py:1546in the PR restores an unguardedROLLBACK. Current main protects this athermes_cli/kanban_db.py:2322-2329so SQLite's auto-rollback does not hide the original EIO/corruption exception.hermes_cli/kanban_db.py:1539assumes every connection returns a file-backedPRAGMA database_listrow. Current boundary tests use a fake connection whoseexecute()returnsNone(tests/hermes_cli/test_kanban_write_txn_busy_retry.py:17-36,62), so this would fail beforeBEGIN IMMEDIATE.- The reported WAL downgrade is already fixed by
5c49cd0e; main now re-raises EIO rather than falling back to DELETE (hermes_state.py:398-408). Main also has narrower dispatcher locking and write-boundary BUSY retry (hermes_cli/kanban_db.py:1416-1497,2296-2341).
Suggested changes
- Rebase the design on current
write_txn()without losing its retry, protected rollback, and cleanup behavior. - Reproduce a remaining current-main failure before adding global write serialization, and distinguish transient EIO from confirmed DB corruption.
Automated hermes-sweeper review.
| lock_path = db_path.with_suffix(db_path.suffix + ".write.lock") | ||
| with _interprocess_file_lock(lock_path): | ||
| conn.execute("BEGIN IMMEDIATE") | ||
| try: |
There was a problem hiding this comment.
write_txn() is currently exercised with fake boundary-test connections whose execute() returns None (tests/hermes_cli/test_kanban_write_txn_busy_retry.py:17-36,62), so this path lookup fails before BEGIN IMMEDIATE. Keep non-file-backed/test connections supported or explicitly branch before requiring PRAGMA database_list.
| raise | ||
| else: | ||
| conn.execute("COMMIT") | ||
|
|
There was a problem hiding this comment.
Please retain the protected rollback behavior now on main: SQLite may have already auto-rolled back after EIO or corruption, and an unguarded ROLLBACK then masks the original storage error with cannot rollback - no transaction is active.
Summary
disk I/O errorinstead of treating it as WAL-incompatible fallbackBEGIN IMMEDIATEWhy
On WSL under concurrent Kanban dispatcher/worker load, a board hit SQLite B-tree corruption after generic
disk I/O errorwas handled like a safe WAL fallback. That let workers continue against degraded storage state. This makes IOERR/malformed/not-a-db fail closed and adds app-level write serialization around board mutations.Test plan
PYTHONPATH=. /home/usmc1/.hermes/hermes-agent/venv/bin/python -m pytest tests/test_hermes_state_wal_fallback.py tests/hermes_cli/test_kanban_db.py tests/hermes_cli/test_kanban_multiprocess_integrity.py tests/gateway/test_kanban_sqlite_fatal_errors.py -o addopts= -qmain:192 passed, 1 warning in 12.78sPRAGMA integrity_check=>ok, counts tasks=480 comments=960 events=1846 runs=406Operational notes
--max 1) and run integrity checks before/after batches until confidence is rebuilt.