Files
hermes-agent/cron/constants.py
kshitijk4poor 6f88751a7e refactor(cron): share is_recurring, the CLI probe-then-read and the report fields
/simplify-code quality pass on the final #133283 stack, no behaviour change:
- One null-safe is_recurring in cron/constants.py replaces scheduler_tick's new copy and
  unreachable_retry's (whose .get("schedule", {}) raised on a null schedule).
- cron status / cron list share _probe_then_list_jobs (probe, print, guarded read) instead of
  two near-identical blocks.
- StoreDegraded.notice_fields and probe_report build their fields through one _report_fields.
- The notice listener's pre-checks no longer repeat deliver()'s store re-check; deliver() is the
  single staleness gate (still red when removed).
2026-10-07 10:20:18 +05:30

23 lines
1.2 KiB
Python

"""Fire-claim timing bounds shared by the job store and its siblings.
Import-free on purpose: a sibling loaded fresh from a newer on-disk tree must resolve
these without going through the ``cron.jobs`` object a long-lived process cached at boot.
"""
# A fire_claim younger than this is a live run (heartbeat cadence is 60 s). One value
# for claiming, one-shot re-arm, and stale-error recovery so they cannot disagree.
FIRE_CLAIM_TTL_SECONDS = 300
# A hosted/webhook fire for the armed slot can arrive a few seconds before the stored
# ``next_run_at`` (the fire scheduler's clock runs ahead of ours). Claims that early still own
# the slot; only claims further ahead are off-tick manual/dashboard fires.
FIRE_CLAIM_SKEW_SECONDS = 60
# Multiplier over HERMES_CRON_TIMEOUT for claim TTLs: the timeout is an *inactivity* limit, not a
# wall-clock cap, so healthy runs may legitimately exceed it and a TTL of exactly the timeout
# would expire live claims.
CLAIM_TTL_INACTIVITY_HEADROOM = 3
def is_recurring(job: dict) -> bool:
"""A cron/interval job (vs a one-shot); a null ``schedule`` counts as not recurring."""
return (job.get("schedule") or {}).get("kind") in {"cron", "interval"}