This commit is contained in:
2026-01-31 19:57:09 -08:00
parent 6513a3ad04
commit 1dbaabac73
7 changed files with 125 additions and 88 deletions

View File

@@ -12,6 +12,8 @@ from contextlib import contextmanager
import time
import datetime
from SYS.logger import debug, log
import logging
logger = logging.getLogger(__name__)
# DB execute retry settings (for transient 'database is locked' errors)
_DB_EXEC_RETRY_MAX = 5
@@ -29,8 +31,8 @@ def _resolve_root_dir() -> Path:
candidate = Path(env_root).expanduser().resolve()
if candidate.exists():
return candidate
except Exception:
pass
except Exception as exc:
logger.debug("_resolve_root_dir: failed to resolve env_root %r: %s", env_root, exc, exc_info=True)
cwd = Path.cwd().resolve()
for base in [cwd, *cwd.parents]:
@@ -173,23 +175,24 @@ class Database:
try:
if not self.conn.in_transaction:
self.conn.rollback()
except Exception:
pass
except Exception as exc:
logger.exception("Rollback failed while retrying locked execute: %s", exc)
time.sleep(delay)
continue
# Not recoverable or out of retries
if not self.conn.in_transaction:
try:
self.conn.rollback()
except Exception:
pass
except Exception as exc:
logger.exception("Rollback failed in non-recoverable execute path: %s", exc)
raise
except Exception:
except Exception as exc:
if not self.conn.in_transaction:
try:
self.conn.rollback()
except Exception:
pass
except Exception as rb_exc:
logger.exception("Rollback failed during unexpected execute exception: %s", rb_exc)
logger.exception("Unexpected exception during DB execute: %s", exc)
raise
def executemany(self, query: str, param_list: List[tuple]):
@@ -211,22 +214,23 @@ class Database:
try:
if not self.conn.in_transaction:
self.conn.rollback()
except Exception:
pass
except Exception as exc:
logger.exception("Rollback failed while retrying locked executemany: %s", exc)
time.sleep(delay)
continue
if not self.conn.in_transaction:
try:
self.conn.rollback()
except Exception:
pass
except Exception as exc:
logger.exception("Rollback failed in non-recoverable executemany path: %s", exc)
raise
except Exception:
except Exception as exc:
if not self.conn.in_transaction:
try:
self.conn.rollback()
except Exception:
pass
except Exception as rb_exc:
logger.exception("Rollback failed during unexpected executemany exception: %s", rb_exc)
logger.exception("Unexpected exception during DB executemany: %s", exc)
raise
@contextmanager
@@ -255,7 +259,7 @@ class Database:
try:
self._conn_lock.release()
except Exception:
pass
logger.exception("Failed to release DB connection lock")
def fetchall(self, query: str, params: tuple = ()):
with self._conn_lock:
@@ -321,17 +325,28 @@ def _log_worker_loop() -> None:
fallback_file = fallback_dir / "log_fallback.txt"
with fallback_file.open("a", encoding="utf-8") as fh:
fh.write(f"{datetime.datetime.utcnow().isoformat()}Z [{level}] {module}: {message}\n")
except Exception:
except Exception as exc:
# Last resort: print to stderr
try:
log(f"ERROR: Could not persist log message: {level} {module} {message}")
except Exception:
pass
try:
import sys as _sys, traceback as _tb
_sys.stderr.write(f"CRITICAL: Could not persist log message to fallback file: {exc}\n")
_tb.print_exc(file=_sys.stderr)
except Exception:
pass
finally:
try:
_LOG_QUEUE.task_done()
except Exception:
pass
except Exception as exc:
try:
import sys as _sys, traceback as _tb
_sys.stderr.write(f"CRITICAL: Failed to mark log task done: {exc}\n")
_tb.print_exc(file=_sys.stderr)
except Exception:
pass
def _ensure_log_thread() -> None:
@@ -433,7 +448,8 @@ def rows_to_config(rows) -> Dict[str, Any]:
parsed_val = val
except Exception:
parsed_val = val
except Exception:
except Exception as exc:
logger.debug("rows_to_config: failed to parse value for key %s; using raw value", key, exc_info=True)
parsed_val = val
if cat == 'global':
@@ -469,7 +485,8 @@ def insert_worker(worker_id: str, worker_type: str, title: str = "", description
(worker_id, worker_type, title, description)
)
return True
except Exception:
except Exception as exc:
logger.exception("Failed to insert worker %s: %s", worker_id, exc)
return False
def update_worker(worker_id: str, **kwargs) -> bool:
@@ -495,7 +512,8 @@ def update_worker(worker_id: str, **kwargs) -> bool:
try:
db.execute(query, tuple(vals))
return True
except Exception:
except Exception as exc:
logger.exception("Failed to update worker %s: %s", worker_id, exc)
return False
def append_worker_stdout(worker_id: str, content: str, channel: str = 'stdout'):
@@ -504,8 +522,8 @@ def append_worker_stdout(worker_id: str, content: str, channel: str = 'stdout'):
"INSERT INTO worker_stdout (worker_id, channel, content) VALUES (?, ?, ?)",
(worker_id, channel, content)
)
except Exception:
pass
except Exception as exc:
logger.exception("Failed to append worker stdout for %s", worker_id)
def get_worker_stdout(worker_id: str, channel: Optional[str] = None) -> str:
query = "SELECT content FROM worker_stdout WHERE worker_id = ?"