Trigger Tokens, Deduplication¶
schedium is designed to be called frequently (for example, once per second) via
schedium.scheduler.Scheduler.run_pending(). Most triggers match for an
interval of time (sometimes a full bucket, sometimes an unbounded window), so
without deduplication the same job would run repeatedly while the trigger
remains satisfied.
schedium avoids that by turning a trigger match into a trigger event token.
Each Job remembers the last token it ran for and will not
run again for the same token.
Where tokens come from¶
A trigger tree is evaluated by schedium.utils.evaluate.evaluate().
Conceptually:
If
trigger.matches(now)is false, the result isNone(no event).If it matches, schedium returns a
TriggerEvent.The job compares
event.tokento its storedlast_event.
Token shapes¶
schedium currently emits tokens in two main forms:
One-shot tokens for
AtDateTime:If an
AtDateTimeexists anywhere in the trigger tree,evaluate(...)returns("at", run_date).This makes one-shot schedules behave like true one-shot events even though
AtDateTime.matches(now)is true for allnow >= run_date.
Bucket tokens for everything else:
("bucket", granularity, truncate(now, granularity))
Here,
truncate(...)floors the timestamp to the bucket start.
Effective granularity¶
Bucket tokens require a granularity. schedium picks an effective granularity from the trigger tree. See Granularity: effective granularity for details.
Why this matters in practice¶
Calling run_pending frequently¶
If you call run_pending every second, you generally want:
jobs to not run again and again within the same minute/hour/day bucket, and
jobs to run immediately when the bucket changes.
Bucket tokens provide exactly that behavior.
Long-lived matches (constraints)¶
Constraint triggers like Between and
BetweenDateTime can match for long windows.
Deduplication prevents jobs from running continuously throughout that window.
Example: with Tick("minute") & BetweenDateTime(...) the job runs at most
once per minute while the datetime window is active.
One-shot schedules¶
AtDateTime matches for all future times.
The special ("at", run_date) token ensures the job runs only once even if
run_pending is called repeatedly after the target time.
Relationship to window time¶
next_window(after)answers: “what validity window comes next?”trigger tokens answer: “did I already run for this trigger event?”
These are intentionally separate concepts:
windows are used to compute future schedule structure (especially for AND/OR combinators), while
tokens are used to provide stable, easy-to-reason-about deduplication for repeated evaluations.
Resetting deduplication¶
Jobs are stateful. If you want to run the same callable under multiple
independent schedules, create multiple Job instances.
If you need to force a job to run again within the same token, you can clear its
stored event token by setting job.last_event = None (or by constructing a
fresh job).