RussellLuo/timingwheel

Add support for scheduling repetitive tasks

Closed this issue · 1 comments

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.

Implemented by #12.