Add support for scheduling repetitive tasks
Closed this issue · 1 comments
RussellLuo commented
Motivation
Currently timingwheel
only supports one-time tasks (via AfterFunc), it's meaningful to provide a general mechanism for supporting repetitive tasks (a.k.a. Cron jobs).
(For Chinese users, also see #8.)
The API
Inspired by cron.Schedule, the API is designed to be as follows:
// Scheduler determines the execution plan of a task.
type Scheduler interface {
// Next returns the next execution time after the given (previous) time.
// It will return a zero time if no next time is scheduled.
Next(time.Time) time.Time
}
// ScheduleFunc calls f (in its own goroutine) according to the execution
// plan scheduled by s.
// It returns a Timer that can be used to cancel the call using its Stop method.
//
// Internally, ScheduleFunc will ask the first execution time (by calling
// s.Next()) initially, and create a timer if the execution time is non-zero.
// Afterwards, it will ask the next execution time each time f is about to
// be executed, and f will be called at the next execution time if the time
// is non-zero.
func (tw *TimingWheel) ScheduleFunc(s Scheduler, f func()) *Timer {
...
}
Usage example
Based on the Scheduler
interface,it's possible for us to implement all kinds of repetitive tasks.
EveryFunc shortcut
As an example (as well as a comparison of #9), the new implementation will be as follows:
type FuncScheduler func(time.Time) time.Time
func (fs FuncScheduler) Next(prev time.Time) time.Time {
return fs(prev)
}
func EveryFunc(d time.Duration, f func()) *Timer {
return tw.ScheduleFunc(FuncScheduler(func(prev time.Time) time.Time {
return prev.Add(d)
}), f)
}
Cron expression
By leveraging cronexpr or cron.Parser to parse Cron expression, it's possible for us to support Cron jobs in a more conventional way.
RussellLuo commented
Implemented by #12.