fix(pipes): don't fire newly-installed or stale cron pipes immediately#3607
Merged
Conversation
A newly-installed pipe has no `last_run`, so the scheduler defaulted to
`UNIX_EPOCH` and asked `cron.after(epoch).next()` — a 1970 slot, which
is always `<= now`, so the pipe fired on the very next scheduler tick.
Same trap when the app was off across a scheduled slot: on restart the
cron would catch up immediately instead of waiting for the next slot.
For wall-clock cron ("every day at 7am") this is wrong — a user who
installs a morning brief at 5:39pm doesn't want it firing 12 seconds
later.
Anchor the cron lookup at `max(last_run, now - 5min)` so we only fire
when we're actually inside a recent scheduled slot. Stale missed slots
(deep past) are skipped and the pipe waits for its next future slot.
The 5-minute window absorbs scheduler-tick latency and brief downtime.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
every day at 7am) were firing immediately on install instead of waiting for their next scheduled slot. A user reported creating a "morning brief" pipe at 5:39pm via chat — it fired 12 seconds later (scheduler: queuing pipe 'morning-brief' (scheduled)).last_run = UNIX_EPOCH, socron.after(epoch).next()returned a 1970-01-01 slot which is always<= now⇒ fire.max(last_run, now - 5min)so we only fire when the most recent slot is actually within a small grace window. Stale missed slots are skipped; the pipe waits for the next future slot.The 5-minute
CRON_GRACE_WINDOWabsorbs scheduler-tick latency (~1s) and brief sleep/wake cycles without firing stale catch-up runs.Interval schedules (
every 1h,every 30m) are untouched — those have always been "fire N seconds after last_run" semantics.Test plan
cargo test --lib -p screenpipe-core pipes::— all 131 tests passtest_should_run_cron_fresh_install_waits— newly-installed pipe (last_run = epoch) does NOT fire immediatelytest_should_run_cron_stale_last_run_waits— pipe whose app was off for 3 days does NOT fire immediately on restarttest_should_run_cron_within_grace_fires— slot hit moments ago, last_run far in past → still firestest_should_run_human_dailyupdated to use minute-precision cron so the slot is "right now" regardless of test wall-clock timeschedule: every day at 9am— verify it does NOT fire on install and DOES fire at 9am the next day