Three fixes for the silent post-restart ticker stall: 1. _jobs_lock() bounds its cross-process flock: LOCK_NB polled against a 30s deadline instead of an unbounded LOCK_EX taken while holding the process-wide RLock. On timeout it logs at ERROR and degrades to in-process-only locking (the existing fallback path), so a sibling process wedged while holding .jobs.lock can no longer freeze every cron function - including the ticker's get_due_jobs() and thus the heartbeat - forever with zero logging. 2. fire_claim/run_claim freshness checks are bounded on both sides (0 <= age < ttl): a claim stamped in the future (clock/TZ skew across a restart) was previously fresh forever, making the job permanently unfireable and every manual run report 'already being fired'. 3. _execute_job_now distinguishes paused/disabled/missing jobs from a genuinely held claim instead of mislabeling them all as 'already being fired'. |
||
|---|---|---|
| .. | ||
| scripts | ||
| __init__.py | ||
| blueprint_catalog.py | ||
| jobs.py | ||
| lifecycle_guard.py | ||
| scheduler.py | ||
| scheduler_provider.py | ||
| suggestion_catalog.py | ||
| suggestions.py | ||