Merge origin/main into ethie/pm-clean
- tools/browser_tool_install.py: keep pm-clean's frozen old-updater stub; main's UTF-8 decode fix touched only the npx prefetch body it replaces. - tests/hermes_cli/test_update_scoped_reconciliation.py: keep pm-clean's test subset (catch-up rides the PM completion owner) and take main's gateway-less host evidence (#120740): the updated seed that holds the host at a running gateway, and the two gateway-less matrices for the source change that merged cleanly into update_cmd_fleet.py.
This commit is contained in:
@@ -979,14 +979,7 @@ class SessionDB(
|
||||
# mutations, not just idempotent UPSERTs.
|
||||
ioerr_begin_retried = False
|
||||
while True:
|
||||
self._raise_if_db_corrupt()
|
||||
if storage_state(self.db_path) == STORAGE_CORRUPT:
|
||||
# Another handle in this process already saw structural damage on this file.
|
||||
# Quarantine this one before it touches SQLite; the error type is the same
|
||||
# StateDbCorruptError, so every transcript-diversion owner handles it unchanged.
|
||||
self._halt_db_corrupt(sqlite3.DatabaseError(
|
||||
"database disk image is malformed (reported earlier in this process: "
|
||||
f"{storage_corrupt_reason(self.db_path)})"))
|
||||
self._raise_if_db_corrupt(storage=True)
|
||||
# NOTE: the replaced/generation live probe runs INSIDE the lock below,
|
||||
# not here. close() mutates _conn and _db_sidecar_identity under that
|
||||
# same lock, ending the WAL generation (SQLite unlinks the -wal/-shm
|
||||
@@ -1078,7 +1071,7 @@ class SessionDB(
|
||||
self._raise_if_db_replaced()
|
||||
# Corrupt FTS shadow tables fail every write via the sync triggers while canonical
|
||||
# rows are intact: detach the derived indexes atomically and retry (never rebuild here).
|
||||
if self._enter_fts_fail_open(exc):
|
||||
if self._enter_fts_fail_open(exc, deadline=deadline, patience_s=patience_s):
|
||||
continue
|
||||
# What survives both checks is structural damage: quarantine.
|
||||
if self._is_structural_corruption_error(exc):
|
||||
@@ -1397,9 +1390,16 @@ class SessionDB(
|
||||
)
|
||||
return retire_without_close
|
||||
|
||||
def _raise_if_db_corrupt(self) -> None:
|
||||
def _raise_if_db_corrupt(self, *, storage: bool = False) -> None:
|
||||
if self._db_corrupt:
|
||||
raise self._corrupt_error()
|
||||
if storage and storage_state(self.db_path) == STORAGE_CORRUPT:
|
||||
# Another handle in this process already saw structural damage on this file.
|
||||
# Quarantine this one before it touches SQLite; the error type is the same
|
||||
# StateDbCorruptError, so every transcript-diversion owner handles it unchanged.
|
||||
self._halt_db_corrupt(sqlite3.DatabaseError(
|
||||
"database disk image is malformed (reported earlier in this process: "
|
||||
f"{storage_corrupt_reason(self.db_path)})"))
|
||||
|
||||
def _sleep_before_write_retry(self, deadline: float, patience_s: float) -> bool:
|
||||
"""Sleep one jitter interval if the budget allows; True = retry, False = deadline passed. Small
|
||||
|
||||
Reference in New Issue
Block a user