Skip to content

Cron loop's sleep-after-work scheduling combined with an independently-anchored lookback window can silently skip a scheduled trigger #2987

Closed

Description

@mstomar125

Problem

A real but rare, self-healing edge case — during long continuous uptime with many/heavy cron entries a scheduled play could silently skip one occurrence, which most users would never notice since the next cycle recovers normally for periodic schedules.

Root cause

cron_runner_loop (packages/core/src/playbook/cron_runner.rs:119) sleeps POLL_INTERVAL (60s) starting only after check_and_enqueue returns, not on a fixed wall-clock cadence. check_and_enqueue independently computes window_start = now - 60s from its own fresh now each call and matches only occurrences in [window_start, now]. If iteration N's processing takes d seconds, iteration N+1's window doesn't reach back far enough to cover that d-second gap, so any occurrence landing there is matched by neither window. check_and_enqueue's unbounded per-entry query_nodes_by_type scan means d (and the vulnerable gap) grows with cron-entry count and dataset size — worse under heavier cron usage, which is exactly when this class of bug matters most.

Suggested fix

Switch cron_runner_loop to tokio::time::interval (fixed wall-clock cadence) instead of sleep-after-work, or persist a "last checked" timestamp across iterations so the lookback window starts exactly where the previous one ended.


Found via the 2026-09-25 full-repo code sweep (finding #42 of 84 in CODE_SWEEP_FINDINGS_2026-09-25.md). Severity: low. Category: risky.

Activity

  1. self-assigned this
    on Sep 25, 2026
  2. removed their assignment
    on Sep 25, 2026
  3. malibio commented on Sep 25, 2026

    @malibio
    Collaborator

    Frontend baseline: 5312 passed, 1 failed (architecture-benchmarks.test.ts timing threshold — known machine-load flake, unrelated)

  4. self-assigned this
    on Sep 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

foundationsweepFound via the 2026-09-25 full-repo code sweep

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions