Files
hermes-agent/tests/cron/test_idle_tick_config_skip.py
T
kshitij 0422479031 perf(cron): skip config load on idle scheduler ticks (idea from #33612)
Re-derivation of #33612 by @LeonSGP43 onto the rewritten scheduler (the
original is 10,692 commits behind; its tick() no longer exists in that
shape, so this is a fresh minimal fix crediting the PR's idea).

The gateway's built-in ticker calls tick(verbose=False) every 60s. The
idle early-return was gated on 'verbose and not due_jobs', so idle
GATEWAY ticks fell through to load_config() + worker-pool resolution
every minute. Return early on ANY idle tick; keep the post-tick MCP
orphan sweep (main intentionally reaps orphaned stdio children on idle
ticks).

3 new tests; mutation-checked (restoring the verbose-gated guard fails
the config-skip test). 66 scheduler tests green.
2026-08-03 17:18:51 +05:30

59 lines
2.0 KiB
Python

"""Idle cron ticks must not load config (#33612 salvage).
The gateway's built-in ticker calls tick(verbose=False) every 60s. Before
the fix, idle ticks (no due jobs) fell through the verbose-only early
return and paid a full load_config() + worker-pool resolution per tick.
The fix returns early on ANY idle tick while preserving the post-tick MCP
orphan sweep that main intentionally runs even when nothing is due.
"""
from __future__ import annotations
from unittest.mock import patch
import cron.scheduler as scheduler_mod
def _run_idle_tick(**kwargs):
"""Run tick() with no due jobs; return (load_config_called, sweep_called)."""
calls = {"load_config": 0, "sweep": 0}
def _fake_load_config(*a, **k):
calls["load_config"] += 1
return {}
def _fake_sweep():
calls["sweep"] += 1
with (
patch.object(scheduler_mod, "get_due_jobs", return_value=[]),
patch.object(scheduler_mod, "load_config", side_effect=_fake_load_config),
patch(
"tools.mcp_tool._kill_orphaned_mcp_children",
side_effect=_fake_sweep,
),
):
rc = scheduler_mod.tick(verbose=kwargs.get("verbose", False))
return rc, calls
class TestIdleTickSkipsConfigLoad:
def test_idle_nonverbose_tick_skips_load_config(self):
"""Gateway-style tick(verbose=False) with no due jobs: no config load."""
rc, calls = _run_idle_tick(verbose=False)
assert rc == 0
assert calls["load_config"] == 0, (
"idle tick must not load config (was loading every 60s in the gateway ticker)"
)
def test_idle_verbose_tick_skips_load_config(self):
rc, calls = _run_idle_tick(verbose=True)
assert rc == 0
assert calls["load_config"] == 0
def test_idle_tick_still_sweeps_mcp_orphans(self):
"""The idle-tick orphan sweep is intentional on main — must survive."""
rc, calls = _run_idle_tick(verbose=False)
assert rc == 0
assert calls["sweep"] == 1, "idle tick must still reap orphaned MCP children"