fix: encode read-only session DB URI

This commit is contained in:
TARS committed 2026-07-03 20:04:41 +02:00
1 parent 47855eed88
commit 10ecfbb376
2 files changed
+47 -2

No files matched your search

+8 -2
View File
@@ -458,9 +458,15 @@ def read_importable_agent_session_rows(
# the agent streams into it adds needless checkpoint/lock surface (#5455).
# The defensive index self-heal below still runs, but through a separate
# short-lived writable connection on the rare missing-index path only.
read_only_uri = f"{db_path.resolve().as_uri()}?mode=ro"
try:
conn = sqlite3.connect(f"file:{db_path}?mode=ro", uri=True)
except sqlite3.Error:
conn = sqlite3.connect(read_only_uri, uri=True)
except sqlite3.Error as exc:
log.warning(
"agent session listing read-only open failed for %s; falling back to writable connection: %s",
db_path,
exc,
)
conn = sqlite3.connect(str(db_path))
with closing(conn):
conn.row_factory = sqlite3.Row
@@ -12,6 +12,7 @@ writable connection. With the index present (the normal case) the read path
performs zero writes; when the index is missing the self-heal still runs and
rows still come back.
"""
import logging
import sqlite3
import api.agent_sessions as agent_sessions
@@ -73,6 +74,44 @@ def test_listing_opens_read_only_and_returns_rows(tmp_path, monkeypatch):
assert "mode=ro" in calls[0]["target"]
def test_listing_read_only_uri_encodes_special_path_chars(tmp_path, monkeypatch):
db_dir = tmp_path / "state dir #1"
db_dir.mkdir()
db = db_dir / "state?.db"
_make_db(db, with_index=True)
calls = _record_connects(monkeypatch)
out = read_importable_agent_session_rows(db, exclude_sources=None)
assert "cli-1" in {r["id"] for r in out}
assert calls[0]["uri"] is True
assert calls[0]["target"].startswith("file://")
assert "%20" in calls[0]["target"]
assert "%23" in calls[0]["target"]
assert "%3F" in calls[0]["target"]
assert calls[0]["target"].endswith("?mode=ro")
def test_read_only_open_fallback_is_logged(tmp_path, monkeypatch, caplog):
db = tmp_path / "state.db"
_make_db(db, with_index=True)
real_connect = sqlite3.connect
def fail_read_only(target, *args, **kwargs):
if kwargs.get("uri"):
raise sqlite3.OperationalError("synthetic read-only URI failure")
return real_connect(target, *args, **kwargs)
monkeypatch.setattr(agent_sessions.sqlite3, "connect", fail_read_only)
with caplog.at_level(logging.WARNING, logger="api.agent_sessions"):
out = read_importable_agent_session_rows(db, exclude_sources=None)
assert "cli-1" in {r["id"] for r in out}
assert "read-only open failed" in caplog.text
assert "synthetic read-only URI failure" in caplog.text
def test_index_present_performs_no_writable_connection(tmp_path, monkeypatch):
db = tmp_path / "state.db"
_make_db(db, with_index=True)