// Package task provides an interface for distributed jobs package task import ( "context" "fmt" "time" ) // Task represents a distributed task type Task interface { // Run runs a command immediately until completion Run(Command) error // Status provides status of last execution Status() string } // Command to be executed type Command struct { Name string Func func() error } // Schedule represents a time or interval at which a task should run type Schedule struct { // When to start the schedule. Zero time means immediately Time time.Time // Non zero interval dictates an ongoing schedule Interval time.Duration } type Options struct { // Pool size for workers Pool int // Alternative options Context context.Context } type Option func(o *Options) func (c Command) Execute() error { return c.Func() } func (c Command) String() string { return c.Name } func (s Schedule) Run() <-chan time.Time { d := s.Time.Sub(time.Now()) ch := make(chan time.Time, 1) go func() { // wait for start time <-time.After(d) // zero interval if s.Interval == time.Duration(0) { ch <- time.Now() close(ch) return } // start ticker ticker := time.NewTicker(s.Interval) defer ticker.Stop() for t := range ticker.C { ch <- t } }() return ch } func (s Schedule) String() string { return fmt.Sprintf("%d-%d", s.Time.Unix(), s.Interval) } // WithPool sets the pool size for concurrent work func WithPool(i int) Option { return func(o *Options) { o.Pool = i } }