diff --git a/CHANGELOG.md b/CHANGELOG.md index 81b55ac9..178ce85f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,18 @@ ### Fixed +- **Opening the sidebar can no longer stall the agent's writes to `state.db`.** Several WebUI + paths that only read the agent's `state.db` could quietly become writers. The read-only opener + fell back to a writable connection when `mode=ro` failed. The session listing self-healed a + missing `idx_messages_session` with `CREATE INDEX` through its own writable connection, which + holds the SQLite writer lock for minutes on a large `messages` table. The cron sidebar, insights + and deep-health checks opened the database with a bare `sqlite3.connect()`. Every one of these + readers now opens strictly read-only (`file:...?mode=ro`) and never creates an index. A missing + index falls back to the existing pre-aggregated listing. The gateway watcher also no longer polls + the database when no client is subscribed. Operators with an older agent can create the read + indexes in a drained maintenance window with `scripts/ensure_state_db_read_indexes.py`; see + `docs/troubleshooting.md`. (#7445 by @ruizanthony) + - **A failed chat launch no longer leaves the session stuck "running".** If the worker thread couldn't start, its stream ownership and the session's pending-stream fields were never cleared, so the session could look permanently active and the registries grew. Launch failure now clears diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 833fbd6a..bb59d431 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -254,7 +254,7 @@ python3 scripts/ensure_state_db_read_indexes.py --db ~/.hermes/state.db --confir - `--confirm-drained` is mandatory: it is your assertion that no agent turn is running against the database. The tool does not verify it. - `--lock-file PATH` (optional) additionally holds an exclusive non-blocking lock on `PATH` (`flock` on POSIX, `msvcrt.locking` on Windows) for deployments that serialise agent turns on a lock file; a held lock makes the tool exit without touching the database. Without `--lock-file` no lock primitive is required, so the script runs on native Windows as well. On Windows the lock covers byte 0 of `PATH`; a new or empty lock file is initialised with one byte first (an existing lock file is never rewritten). - The tool opens the database `mode=rw` (never `rwc`): a mistyped path raises instead of creating an empty database. Indexes are created inside one `BEGIN IMMEDIATE` transaction and rolled back on any error. -- It is idempotent and prints a JSON status per index (`created` / `existing`). An existing index with a different table, key shape or collation is reported as `Incompatible index` and never replaced; an index that is not covering (`EXPLAIN QUERY PLAN`) is reported as `Index is not covering`. +- It is idempotent and prints a JSON status per index (`created` / `existing` / `skipped`). `skipped` means this database's schema lacks a column that index keys on (an older agent); the indexes the schema does support are still created. An existing index with a different table, key shape or collation is reported as `Incompatible index` and never replaced; an index that is not covering (`EXPLAIN QUERY PLAN`) is reported as `Index is not covering`. - Windows UNC profiles (`HERMES_HOME=\\server\share\...`) are supported: readers and this tool build the empty-authority URI `file:////server/share/state.db` that the bundled SQLite accepts. **When to file a bug.** File a WebUI bug if the listing stays slow after the tool reports `existing` for `idx_messages_session`, if the tool reports `Incompatible index` on an untouched agent-created database, or if a read-only open fails on a local path. Include the tool's JSON output, the `PRAGMA index_list(messages)` result, and the sanitized error text.