package task import ( "crypto/sha1" "fmt" "io" "reflect" "time" ) type TaskSchedule struct { IsRecurring bool LastRun time.Time NextRun time.Time Duration time.Duration } type Task struct { *TaskSchedule TaskTarget *TaskTarget Params []interface{} } // New returns an instance of task func New(taskTarget *TaskTarget, params []interface{}) *Task { return &Task{ TaskSchedule: &TaskSchedule{}, TaskTarget: taskTarget, Params: params, } } // NewWithSchedule creates an instance of task with the provided schedule information func NewWithSchedule(taskTarget *TaskTarget, params []interface{}, taskSchedule *TaskSchedule) *Task { return &Task{ TaskSchedule: taskSchedule, TaskTarget: taskTarget, Params: params, } } // IsDue returns a boolean indicating whether the task should execute or not func (t *Task) IsDue() bool { timeNow := time.Now() return timeNow == t.NextRun || timeNow.After(t.NextRun) } // Run will execute the task and schedule it's next run. func (t *Task) Run() { // Reschedule task first to prevent running the task // again in case the execution time takes more than the // task's duration value. t.scheduleNextRun() fv := reflect.ValueOf(t.TaskTarget.targetFunc) params := make([]reflect.Value, len(t.Params)) for i, param := range t.Params { params[i] = reflect.ValueOf(param) } fv.Call(params) } // Hash will return the SHA1 representation of the task's data. func (t *Task) Hash() string { hash := sha1.New() _, _ = io.WriteString(hash, t.TaskTarget.Name) _, _ = io.WriteString(hash, fmt.Sprintf("%+v", t.Params)) _, _ = io.WriteString(hash, fmt.Sprintf("%s", t.TaskSchedule.Duration)) _, _ = io.WriteString(hash, fmt.Sprintf("%t", t.TaskSchedule.IsRecurring)) return fmt.Sprintf("%x", hash.Sum(nil)) } func (t *Task) scheduleNextRun() { if !t.IsRecurring { return } t.LastRun = t.NextRun t.NextRun = t.NextRun.Add(t.Duration) }