polish(mem): readonly config read, debug-level trim logs, loud frame test
Simplify-pass follow-up on the #66355 salvage: 1. _config_settings runs on EVERY trim attempt (before the cooldown check) and only reads — swap load_config for load_config_readonly. Deep-copying the whole config per attempt generates exactly the allocator garbage this module exists to release. Tests re-seamed. 2. Trim-failure logs demoted warning->debug at all 3 periodic sites (gateway housekeeping, idle reaper, slash worker): sibling failure branches in the same loops log at debug, and a persistent failure (e.g. broken import after a partial update) would otherwise warn every 60s forever. 3. The frame-inspection test now asserts the expected locals exist before reading them — a rename in _run_prompt_submit fails the test loudly instead of vacuously passing on None.
This commit is contained in:
+5
-1
@@ -25436,7 +25436,11 @@ def _start_gateway_housekeeping(stop_event: threading.Event, adapters=None, loop
|
||||
|
||||
trim_memory(reason="messaging gateway housekeeping")
|
||||
except Exception as exc:
|
||||
logger.warning(
|
||||
# debug, not warning: sibling housekeeping branches all log
|
||||
# failures at debug, and a persistent failure (e.g. broken
|
||||
# import after a partial update) would otherwise warn every
|
||||
# 60s forever.
|
||||
logger.debug(
|
||||
"gateway housekeeping memory trim failed: %s: %s",
|
||||
type(exc).__name__,
|
||||
exc,
|
||||
|
||||
@@ -37,9 +37,14 @@ def _config_settings() -> tuple[bool, float, int, float]:
|
||||
log_every_n: Any = _DEFAULT_LOG_EVERY_N
|
||||
info_log_min_delta_mb: Any = _DEFAULT_INFO_LOG_MIN_DELTA_MB
|
||||
try:
|
||||
from hermes_cli.config import load_config
|
||||
# Read-only access: settings are only .get()ed and coerced, never
|
||||
# mutated — use the no-deepcopy variant. This runs on EVERY trim
|
||||
# attempt (before the cooldown check), and generating a full-config
|
||||
# deepcopy per attempt is exactly the allocator garbage this module
|
||||
# exists to release.
|
||||
from hermes_cli.config import load_config_readonly
|
||||
|
||||
config = load_config() or {}
|
||||
config = load_config_readonly() or {}
|
||||
context = config.get("context") if isinstance(config, dict) else None
|
||||
settings = context.get("memory_trim") if isinstance(context, dict) else None
|
||||
if isinstance(settings, dict):
|
||||
|
||||
@@ -144,7 +144,7 @@ def test_config_cooldown_controls_rate_limit(monkeypatch):
|
||||
monkeypatch.setattr(mem_trim, "_last_trim_monotonic", 1.0)
|
||||
monkeypatch.setattr(mem_trim.time, "monotonic", lambda: 100.0)
|
||||
monkeypatch.setattr(
|
||||
"hermes_cli.config.load_config",
|
||||
"hermes_cli.config.load_config_readonly",
|
||||
lambda: {
|
||||
"context": {
|
||||
"memory_trim": {"enabled": True, "cooldown_seconds": 120.0}
|
||||
@@ -161,7 +161,7 @@ def test_legacy_environment_switch_does_not_control_behavior(monkeypatch):
|
||||
monkeypatch.setattr(mem_trim, "_malloc_trim", trim)
|
||||
monkeypatch.setenv("HERMES_DISABLE_MEMORY_TRIM", "1")
|
||||
monkeypatch.setattr(
|
||||
"hermes_cli.config.load_config",
|
||||
"hermes_cli.config.load_config_readonly",
|
||||
lambda: {"context": {"memory_trim": {"enabled": True}}},
|
||||
)
|
||||
|
||||
|
||||
@@ -14186,7 +14186,7 @@ def test_reap_idle_sessions_logs_trim_failure(monkeypatch, caplog):
|
||||
monkeypatch.setattr(mem_trim, "trim_memory", lambda **_kw: (_ for _ in ()).throw(RuntimeError("boom")))
|
||||
server._sessions.clear()
|
||||
try:
|
||||
with caplog.at_level("WARNING", logger="tui_gateway.server"):
|
||||
with caplog.at_level("DEBUG", logger="tui_gateway.server"):
|
||||
server._reap_idle_sessions()
|
||||
assert "idle reaper memory trim failed: RuntimeError: boom" in caplog.text
|
||||
finally:
|
||||
@@ -15610,6 +15610,12 @@ def test_prompt_submit_releases_old_history_before_heap_trim(monkeypatch):
|
||||
frame = inspect.currentframe()
|
||||
assert frame is not None and frame.f_back is not None
|
||||
caller_locals = frame.f_back.f_locals
|
||||
# Loud, not vacuous: if the production locals are ever renamed, fail
|
||||
# the test instead of silently reading None and "passing".
|
||||
assert "history" in caller_locals and "run_kwargs" in caller_locals, (
|
||||
"expected locals not found in _run_prompt_submit's finally frame — "
|
||||
"renamed? update this test"
|
||||
)
|
||||
observed["history"] = caller_locals.get("history")
|
||||
observed["run_kwargs"] = caller_locals.get("run_kwargs")
|
||||
|
||||
|
||||
@@ -1064,7 +1064,9 @@ def _reap_idle_sessions() -> None:
|
||||
|
||||
trim_memory(reason="idle reaper periodic trim")
|
||||
except Exception as exc:
|
||||
logger.warning(
|
||||
# debug, not warning — persistent failure would repeat every reaper
|
||||
# scan (300s) forever; sibling failure branches log at debug.
|
||||
logger.debug(
|
||||
"idle reaper memory trim failed: %s: %s", type(exc).__name__, exc
|
||||
)
|
||||
|
||||
|
||||
@@ -183,7 +183,9 @@ def main():
|
||||
|
||||
trim_memory(reason="slash worker command completion")
|
||||
except Exception as exc:
|
||||
logger.warning(
|
||||
# debug, not warning — a persistent failure would repeat on
|
||||
# every slash command forever.
|
||||
logger.debug(
|
||||
"slash worker memory trim failed: %s: %s",
|
||||
type(exc).__name__,
|
||||
exc,
|
||||
|
||||
Reference in New Issue
Block a user