Expand description
Scheduled-task lifecycle: run caps, deadlines, and random (“spontaneous”) cadences.
Design rule: flexibility never bends the state machine. Every lifecycle
feature resolves to the SAME primitive the scheduler already trusts —
“either there is a concrete next_run, or the task transitions to
completed with a logged reason”. No new statuses, no background
bookkeeping; all decisions are pure functions over the task row, so every
edge is unit-testable without a database or a clock.
Cadence types:
cron— unchanged (6-field expression, timezone-aware).once— unchanged (single ISO timestamp).random— NEW:schedule_valueis a duration range like"2h..3d"; after each run the next firing lands uniformly at random inside the window. Units:s,m,h,d,w,mo(≈30d). The window is clamped to [1 minute, 366 days] so a typo can neither hot-loop the scheduler nor silence a task for years.
Lifecycle limits (orthogonal, apply to any cadence):
max_runs— retire the task ascompletedonce it has run N times.not_after— retire the task ascompletedonce the next firing would land past the deadline (checked again at claim time, so a task that was already queued cannot fire after its deadline either).
Enums§
- Next
RunDecision - Outcome of post-run scheduling for a recurring task.
Functions§
- deadline_
passed - True when the task’s deadline has already passed — checked at claim time
so an already-queued task cannot fire after
not_after. - decide_
next_ run - Decide what happens to a recurring (
cron|random) task after a run.run_count_afteris the count INCLUDING the run that just finished. - describe_
schedule - Human cadence summary for task listings.
- humanize_
until - Compact “in 3h 12m” / “overdue” rendering for a future RFC 3339 instant.
- parse_
duration - Parse a single duration like
45s,30m,2h,3d,1w,2mo. - parse_
duration_ range - Parse a
randomschedule window:"2h..3d"(also accepts"2h-3d"). Clamped to [1 minute, 366 days]; min must not exceed max. - random_
unit - Entropy in [0, 1) without adding an RNG dependency: the v4 UUID source is already a CSPRNG. Scheduling jitter needs unpredictability, not statistics.
- sample_
random_ next - Uniform sample inside the window.
unitis injected (0.0 ≤ unit < 1.0) so tests are deterministic; production passesrandom_unit.