Schedules
A schedule starts Runs of a Task on a clock. You declare it in code, and the server creates the Runs.
Add a schedule to a Task
Pass runcoil.Schedule when you add the Task. This code is from the schedule example. It builds a daily report at 09:00 UTC, with SkipOverlap:
sched := schedule.Cron("0 9 * * *", schedule.SkipOverlap())
// ...
worker.NewTask("daily-report", runcoil.HandlerFunc(handler.dailyReport),
runcoil.Schedule(sched),
runcoil.Retry(runcoil.RetryPolicy{MaxAttempts: 3}),
)A Task has at most one schedule, and a scheduled Run has no input. A new registration of the Task without runcoil.Schedule removes its schedule.
Pick a schedule
The schedule package has three constructors.
| Constructor | Ticks | Example |
|---|---|---|
schedule.Every(d) | Every d, at least 1 second | schedule.Every(time.Minute) |
schedule.Cron(expr) | A five-field cron expression | schedule.Cron("0 9 * * *") |
schedule.Daily(times...) | Each time of day you list | schedule.Daily(schedule.At(9, 0)) |
schedule.Every counts ticks from the Unix epoch, so every tick is a multiple of d. An interval that does not divide 24 hours falls at a different time of day on each day. For a fixed time of day, use Cron or Daily.
schedule.At(hour, minute) takes an hour from 0 to 23 and a minute from 0 to 59. A Cron expression must not start with TZ= or CRON_TZ=.
Read schedules in UTC
Every schedule runs in UTC. There is no other time zone. The server computes the ticks.
Skip overlapping ticks
Pass schedule.SkipOverlap() to Cron or Every. At a tick, if the previous Run of the schedule has not finished, the server creates no Run for that tick. Without it, a new Run starts beside the old one.
A Run that is still queued counts as unfinished.
Use the buttons to compare what happens with and without SkipOverlap, and when the server is down.
A schedule ticks every minute in UTC. With SkipOverlap, the server creates a Run for a tick only when the previous Run of the schedule has finished. Run 2 is still running at the 12:02 and 12:03 ticks, so those two ticks create no Run.
- 12:00 UTC tick. The server creates Run 1.
- 12:01 UTC tick. The server creates Run 2.
- 12:02 UTC tick. Run 2 is still running and SkipOverlap is set, so the server creates no Run for this tick.
- 12:03 UTC tick. Run 2 is still running and SkipOverlap is set, so the server creates no Run for this tick.
- 12:04 UTC tick. The server creates Run 3.
- 12:05 UTC tick. The server creates Run 4.
- 12:06 UTC tick. The server creates Run 5.
Fail a Run that starts late
Pass runcoil.StartDeadline(d) to fail a Run that has not started d after it was due. For example, no worker may have been ready. Without a deadline, a late Run still runs.
Missed ticks create no Run
If a tick passes while the server is down, the server creates no Run for it. The server does not catch up when it returns. The next tick creates a Run as usual.
Know which tick created a Run
Inside a handler, runcoil.Info(ctx).ScheduledAt is the tick that created the Run. It is zero for a Run that a schedule did not create. A retry keeps the original tick. The schedule example uses it to build the same report day after a retry past midnight:
info := runcoil.Info(ctx)
day := info.ScheduledAt.UTC().Truncate(24*time.Hour).AddDate(0, 0, -1)Try it locally
The schedule example runs daily at 09:00 UTC. To see it tick without waiting, set REPORT_INTERVAL, which replaces the daily schedule with schedule.Every:
REPORT_INTERVAL=3s go run ./examples/schedule