fix(delegation): expose state durability barriers
This commit is contained in:
@@ -2877,6 +2877,16 @@ def _reapply_durability_barriers(conn: sqlite3.Connection) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def apply_durability_barriers(conn: sqlite3.Connection) -> bool:
|
||||
"""Apply state-store durability barriers without changing journal mode.
|
||||
|
||||
This is the public entry point for secondary users of ``state.db`` that
|
||||
must inherit its owner's journal mode while retaining per-connection
|
||||
durability settings.
|
||||
"""
|
||||
return _reapply_durability_barriers(conn)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def _exclusive_repair_db_guard(db_path: Path):
|
||||
"""Yield one live connection that excludes writers for repair surgery.
|
||||
|
||||
@@ -66,11 +66,8 @@ def _drain_for(delegation_id, timeout=5.0):
|
||||
return None
|
||||
|
||||
|
||||
def test_schema_init_preserves_shared_state_db_journal_mode(tmp_path, monkeypatch):
|
||||
def test_schema_init_preserves_shared_state_db_journal_mode(tmp_path):
|
||||
"""The delegation ledger is a guest in state.db, not its mode owner."""
|
||||
import hermes_state
|
||||
|
||||
monkeypatch.setattr(hermes_state, "is_sqlite_wal_reset_vulnerable", lambda: False)
|
||||
conn = sqlite3.connect(tmp_path / "state.db")
|
||||
try:
|
||||
assert conn.execute("PRAGMA journal_mode=DELETE").fetchone()[0] == "delete"
|
||||
@@ -86,6 +83,23 @@ def test_schema_init_preserves_shared_state_db_journal_mode(tmp_path, monkeypatc
|
||||
conn.close()
|
||||
|
||||
|
||||
def test_schema_init_preserves_shared_state_db_wal_mode(tmp_path):
|
||||
"""Schema initialization must not replace an existing WAL mode."""
|
||||
conn = sqlite3.connect(tmp_path / "state.db")
|
||||
try:
|
||||
assert conn.execute("PRAGMA journal_mode=WAL").fetchone()[0] == "wal"
|
||||
|
||||
ad._initialize_schema(conn)
|
||||
|
||||
assert conn.execute("PRAGMA journal_mode").fetchone()[0] == "wal"
|
||||
assert conn.execute(
|
||||
"SELECT name FROM sqlite_master WHERE type='table' "
|
||||
"AND name='async_delegations'"
|
||||
).fetchone() == ("async_delegations",)
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
@pytest.mark.macos_only
|
||||
def test_connect_preserves_wal_and_applies_macos_durability_barriers(
|
||||
tmp_path, monkeypatch
|
||||
|
||||
@@ -140,14 +140,17 @@ def _connect() -> sqlite3.Connection:
|
||||
|
||||
|
||||
def _initialize_schema(conn: sqlite3.Connection) -> None:
|
||||
from hermes_state import _reapply_durability_barriers
|
||||
from hermes_state import apply_durability_barriers
|
||||
|
||||
# state.db's owning SessionDB connection establishes the configured journal
|
||||
# mode. This secondary durability ledger must preserve that mode: applying
|
||||
# WAL here on every short-lived connection requires an exclusive lock when
|
||||
# the file is not already WAL and can collide with live transcript/FTS
|
||||
# writers. The ledger works in either WAL or DELETE mode.
|
||||
_reapply_durability_barriers(conn)
|
||||
# writers. The ledger works in either WAL or DELETE mode; if it opens a new
|
||||
# file first, the default rollback journal remains valid until SessionDB
|
||||
# establishes the configured mode. sqlite3.connect(timeout=10) above also
|
||||
# gives its small transactions a busy handler for ordinary contention.
|
||||
apply_durability_barriers(conn)
|
||||
conn.execute(
|
||||
"""CREATE TABLE IF NOT EXISTS async_delegations (
|
||||
delegation_id TEXT PRIMARY KEY,
|
||||
|
||||
Reference in New Issue
Block a user