scheduler
represents sequence(s) of planned events or schedules
dispatched on the scheduler's notification channel C.
When a Schedule's time expires, the schedule is sent as an Entry
on C.
// initialize a scheduler
sched := scheduler.New()
_ = sched.Start()
// start a receiver
go func(sched *scheduler.Scheduler) {
for {
select {
case entry, ok := <-sched.C():
if !ok {
return
}
s := entry.S()
// do something with the schedule
// potentially in a goroutine
// go func(s scheduler.Schedule) { s.Fn()() }(s)
s.Fn()()
// other select cases
case ...
}
}
}(sched)
// stop the scheduler when done
_ = sched.Stop()
The scheduler can be started either empty (using function Start()
as above) or with known schedules using function Run(schedules []*Schedule)
.
Once the scheduler is running, schedules can be added or removed. The scheduler can also return a dump of the current schedules.
The default scheduler (using New
) is initialized with a buffered channel of size 1 and configured such that if the
receiver is slow handling schedules and the buffer is full, the scheduler waits at most 20 millis before giving up.
These options are configurable through Options
passed to function NewScheduler
.
Below an Options
example with a zero channel size and skipping schedules after 1 millisecond when the channel is full:
return &Options{
ChannelSize: 0,
OnChannelFull: OnChannelFull{
MaxWait: time.Millisecond,
},
}
For cases of processes where the monotonic clock may stop, but the system clock continues, eg. when a VM is paused or a laptop hibernated,
options may include a ClockHealth
attribute.
When enabled the clock skew is checked every PollPeriod
and when the clock skew exceeds MaxClockSkew
, the scheduler recomputes the delay
to fire the next reschedule.
...
ClockHealth: ClockHealth{
Enabled: true,
MaxClockSkew: time.Second * 3,
PollPeriod: time.Second,
},
The scheduler has helper functions to add simple schedules:
- firing at a given date:
Scheduler.At(at utc.UTC, o interface{}) ScheduleID
- firing after a given duration:
Scheduler.In(d time.Duration, o interface{}) ScheduleID
More sophisticated schedules are added via function Scheduler.Add(sc *Schedule) bool
.
A Schedule
is built via function NewSchedule(id string, o interface{}, opts ...ScheduleOpt) (*Schedule, error)
scheduler.Occur
are options to build a one time schedule or the initial date of a recurrent schedule:
At( date )
specifies the date when to fire the schedule.In( duration )
specifies a duration after which the schedule must be fired. The exact date is computed when the scheduler receives the schedule.
There are two manners to make a recurrent schedule:
- call function
Reschedule(t utc.UTC)
on the received schedule in the receiver code, or - use a
Recur
option when building the schedule. Note that for a schedule built using aRecur
option, callingReschedule
has no effect.
Using Reschedule(t utc.UTC)
might be preferred when a function is attached to the schedule and the goal is to plan the
next execution after the attached function has run.
By contrast, when using a Recur
option, the next firing date is computed immediately after the schedule was sent to
the notification channel.
scheduler.Recur
options to build recurring schedules:
Next(n Nexter)
uses aNexter
object to compute the next firing date.Every(d time.Duration)
makes the schedule fire every given duration.NextTime(fn func(t time.Time) time.Time)
computes the next time the schedule must fireCron(schedule cron.Schedule)
uses a cron/v3 schedule object.
Note that a Nexter
can also be built around cronexpr
The first date of a recurring schedule is computed via the recurring option when the scheduler receives the schedule
unless an initial date was given via an Occur
option.
note: when a schedule is recurrent, the scheduler dispatches it to the channel, then computes the next occurrence and plans it. However, if the receiver is slow in handling schedules and the schedule is still in the buffer of the channel, the schedule in not dispatched and the next occurrence is computed and planned. This ensures that slow receivers won't lead to overflowing the channel with unhandled schedules.
scheduler.Until
options provide conditions to tell the scheduler to stop rescheduling schedules built via a Recur
option:
Count(count int)
limits the number of times the schedule is fired.Date(u utc.UTC)
specifies a maximum date for the schedule.Elapsed(d time.Duration)
is the maximum duration of the schedule after first dispatching.
If both Date
and Elapsed
are specified, the earliest resulting date is used.
- A cron library for go: cron/V3
- A Golang Job Scheduling Package: gocron (original project)