perf(db): cache SQLite schema init and optimize descendant traversal

- Cache SQLite schema initialization status process-wide in hermes_state.py to prevent redundant column reconciliations and FTS probe queries on every SessionDB connection creation. This eliminates SQLite lock contention under high concurrent requests (e.g. status polls). Bypassed in pytest/unittest environments for mock compatibility.
- Optimize the _session_latest_descendant query in hermes_cli/web_server.py using a recursive CTE (WITH RECURSIVE) to query only descendants of the target session. This avoids downloading and parsing all historical sessions in Python.
This commit is contained in:
sebastianlutycz 2026-06-04 14:52:36 +00:00
parent 62f0cfd902
commit 8ed5e54f65
2 changed files with 25 additions and 2 deletions

View file

@ -4478,7 +4478,17 @@ def _session_latest_descendant(session_id: str):
rows = []
if conn is not None:
raw_rows = conn.execute(
"SELECT id, parent_session_id, started_at FROM sessions"
"""
WITH RECURSIVE descendants(id, parent_session_id, started_at) AS (
SELECT id, parent_session_id, started_at FROM sessions WHERE id = ?
UNION ALL
SELECT s.id, s.parent_session_id, s.started_at
FROM sessions s
JOIN descendants d ON s.parent_session_id = d.id
)
SELECT id, parent_session_id, started_at FROM descendants WHERE id != ?
""",
(sid, sid)
).fetchall()
for row in raw_rows:
rows.append({

View file

@ -19,6 +19,7 @@ import logging
import random
import re
import sqlite3
import sys
import threading
import time
from pathlib import Path
@ -72,6 +73,9 @@ _last_init_error_lock = threading.Lock()
_wal_fallback_warned_paths: set[str] = set()
_wal_fallback_warned_lock = threading.Lock()
_initialized_dbs: Dict[str, Dict[str, Any]] = {}
_db_init_lock = threading.Lock()
_FTS_TRIGGERS = (
"messages_fts_insert",
"messages_fts_delete",
@ -421,7 +425,16 @@ class SessionDB:
apply_wal_with_fallback(self._conn, db_label="state.db")
self._conn.execute("PRAGMA foreign_keys=ON")
self._init_schema()
db_path_str = str(self.db_path.resolve())
is_testing = "pytest" in sys.modules or "unittest" in sys.modules
with _db_init_lock:
if not is_testing and db_path_str in _initialized_dbs:
self._fts_enabled = _initialized_dbs[db_path_str]["fts_enabled"]
else:
self._init_schema()
_initialized_dbs[db_path_str] = {
"fts_enabled": self._fts_enabled
}
except Exception as exc:
# Capture the cause so /resume and friends can surface WHY the
# session DB is unavailable instead of a bare "Session database