fix(state): retry contended session list queries - #102621
ialmeida-jera wants to merge 1 commit into
Conversation
PR #102621 — fix(state): retry contended session list queriesWell-constructed reliability fix: the lock classifier is deliberately narrow (exact-match + Non-blocking nits:
No correctness concerns; the narrow classifier is the key thing and it's right. |
dbf6ec9 to
1fbb318
Compare
Retry only SQLITE_BUSY/SQLITE_LOCKED failures at the list page, pinned backfill, and count query boundaries. Keep retries bounded and emit contention telemetry while unrelated OperationalErrors continue to surface.
1fbb318 to
ac81f4d
Compare
|
Review follow-up completed on current upstream main. Exact head |
What does this PR do?
Retries transient SQLite query-execution contention in the session-list path instead of returning an intermittent error after SQLite's own busy timeout expires.
The retry is intentionally narrow and bounded:
SQLITE_BUSY/SQLITE_LOCKED(including extended result codes) and SQLite's canonical lock messages qualify;sqlite3.OperationalErrorvalues propagate immediately.This is still required on current
main: read-only open contention already has retry handling, but query execution does not. Open PR #101042 changes connectionbusy_timeout; it does not retry a statement after that timeout expires, and it targets #101035 rather than this pinned-query incident.Related Issue
Type of Change
Changes Made
hermes_state.py— add narrow BUSY/LOCKED classification, bounded jittered retry/telemetry, and route page, pinned, and count reads through it.tests/test_session_list_lock_retry.py— deterministic two-connection lock reproduction, persistent-lock budget/telemetry assertions, narrow classifier coverage, and unrelated-error sabotage.tests/hermes_cli/test_web_server.py— proveGET /api/sessionsrecovers both from a locked page query and a lock acquired between listing and count.How to Test
BEGIN EXCLUSIVEfrom a second DELETE-journal connection with the read connection's test-onlybusy_timeout=0.list_sessions_rich()orGET /api/sessions; release the lock during the deterministic backoff.no such tableis never retried.Commands run:
Red/sabotage proof: reverting only
hermes_state.pymadetests/test_session_list_lock_retry.pyfail 4 tests (database is locked/ missing retry boundary); restoring the implementation returned it to green.A full
HERMES_TEST_FILE_RETRIES=0 scripts/run_tests.shrun was also attempted. It failed in 83 unrelated files (248 tests) plus 53 collection/import failures due the local optional-dependency/tool environment (for example disabled lazy install forparallel-web, hostsort/manbehavior). All changed and adjacent state/web suites above are green.Checklist
Code
Documentation & Housekeeping
cli-config.yaml.example— N/ACONTRIBUTING.md/AGENTS.md— N/AScreenshots / Logs
N/A — backend concurrency fix with automated regression coverage.