// Copyright 2014 beego Author. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package toolbox import ( "context" "sort" "time" "github.com/astaxie/beego/task" ) // The bounds for each field. var ( AdminTaskList map[string]Tasker ) const ( // Set the top bit if a star was included in the expression. starBit = 1 << 63 ) // Schedule time taks schedule type Schedule task.Schedule // TaskFunc task func type type TaskFunc func() error // Tasker task interface type Tasker interface { GetSpec() string GetStatus() string Run() error SetNext(time.Time) GetNext() time.Time SetPrev(time.Time) GetPrev() time.Time } // task error type taskerr struct { t time.Time errinfo string } // Task task struct // Deprecated type Task struct { // Deprecated Taskname string // Deprecated Spec *Schedule // Deprecated SpecStr string // Deprecated DoFunc TaskFunc // Deprecated Prev time.Time // Deprecated Next time.Time // Deprecated Errlist []*taskerr // like errtime:errinfo // Deprecated ErrLimit int // max length for the errlist, 0 stand for no limit delegate *task.Task } // NewTask add new task with name, time and func func NewTask(tname string, spec string, f TaskFunc) *Task { task := task.NewTask(tname, spec, func(ctx context.Context) error { return f() }) return &Task{ delegate: task, } } // GetSpec get spec string func (t *Task) GetSpec() string { t.initDelegate() return t.delegate.GetSpec(context.Background()) } // GetStatus get current task status func (t *Task) GetStatus() string { t.initDelegate() return t.delegate.GetStatus(context.Background()) } // Run run all tasks func (t *Task) Run() error { t.initDelegate() return t.delegate.Run(context.Background()) } // SetNext set next time for this task func (t *Task) SetNext(now time.Time) { t.initDelegate() t.delegate.SetNext(context.Background(), now) } // GetNext get the next call time of this task func (t *Task) GetNext() time.Time { t.initDelegate() return t.delegate.GetNext(context.Background()) } // SetPrev set prev time of this task func (t *Task) SetPrev(now time.Time) { t.initDelegate() t.delegate.SetPrev(context.Background(), now) } // GetPrev get prev time of this task func (t *Task) GetPrev() time.Time { t.initDelegate() return t.delegate.GetPrev(context.Background()) } // six columns mean: // second:0-59 // minute:0-59 // hour:1-23 // day:1-31 // month:1-12 // week:0-6(0 means Sunday) // SetCron some signals: // *: any time // ,:  separate signal //    -:duration // /n : do as n times of time duration // /////////////////////////////////////////////////////// // 0/30 * * * * * every 30s // 0 43 21 * * * 21:43 // 0 15 05 * * *    05:15 // 0 0 17 * * * 17:00 // 0 0 17 * * 1 17:00 in every Monday // 0 0,10 17 * * 0,2,3 17:00 and 17:10 in every Sunday, Tuesday and Wednesday // 0 0-10 17 1 * * 17:00 to 17:10 in 1 min duration each time on the first day of month // 0 0 0 1,15 * 1 0:00 on the 1st day and 15th day of month // 0 42 4 1 * *     4:42 on the 1st day of month // 0 0 21 * * 1-6   21:00 from Monday to Saturday // 0 0,10,20,30,40,50 * * * *  every 10 min duration // 0 */10 * * * *        every 10 min duration // 0 * 1 * * *         1:00 to 1:59 in 1 min duration each time // 0 0 1 * * *         1:00 // 0 0 */1 * * *        0 min of hour in 1 hour duration // 0 0 * * * *         0 min of hour in 1 hour duration // 0 2 8-20/3 * * *       8:02, 11:02, 14:02, 17:02, 20:02 // 0 30 5 1,15 * *       5:30 on the 1st day and 15th day of month func (t *Task) SetCron(spec string) { t.initDelegate() t.delegate.SetCron(spec) } func (t *Task) initDelegate() { if t.delegate == nil { t.delegate = &task.Task{ Taskname: t.Taskname, Spec: (*task.Schedule)(t.Spec), SpecStr: t.SpecStr, DoFunc: func(ctx context.Context) error { return t.DoFunc() }, Prev: t.Prev, Next: t.Next, ErrLimit: t.ErrLimit, } } } // Next set schedule to next time func (s *Schedule) Next(t time.Time) time.Time { return (*task.Schedule)(s).Next(t) } // StartTask start all tasks func StartTask() { task.StartTask() } // StopTask stop all tasks func StopTask() { task.StopTask() } // AddTask add task with name func AddTask(taskname string, t Tasker) { task.AddTask(taskname, &oldToNewAdapter{delegate: t}) } // DeleteTask delete task with name func DeleteTask(taskname string) { task.DeleteTask(taskname) } // ClearTask clear all tasks func ClearTask() { task.ClearTask() } // MapSorter sort map for tasker type MapSorter task.MapSorter // NewMapSorter create new tasker map func NewMapSorter(m map[string]Tasker) *MapSorter { newTaskerMap := make(map[string]task.Tasker, len(m)) for key, value := range m { newTaskerMap[key] = &oldToNewAdapter{ delegate: value, } } return (*MapSorter)(task.NewMapSorter(newTaskerMap)) } // Sort sort tasker map func (ms *MapSorter) Sort() { sort.Sort(ms) } func (ms *MapSorter) Len() int { return len(ms.Keys) } func (ms *MapSorter) Less(i, j int) bool { if ms.Vals[i].GetNext(context.Background()).IsZero() { return false } if ms.Vals[j].GetNext(context.Background()).IsZero() { return true } return ms.Vals[i].GetNext(context.Background()).Before(ms.Vals[j].GetNext(context.Background())) } func (ms *MapSorter) Swap(i, j int) { ms.Vals[i], ms.Vals[j] = ms.Vals[j], ms.Vals[i] ms.Keys[i], ms.Keys[j] = ms.Keys[j], ms.Keys[i] } func init() { AdminTaskList = make(map[string]Tasker) } type oldToNewAdapter struct { delegate Tasker } func (o *oldToNewAdapter) GetSpec(ctx context.Context) string { return o.delegate.GetSpec() } func (o *oldToNewAdapter) GetStatus(ctx context.Context) string { return o.delegate.GetStatus() } func (o *oldToNewAdapter) Run(ctx context.Context) error { return o.delegate.Run() } func (o *oldToNewAdapter) SetNext(ctx context.Context, t time.Time) { o.delegate.SetNext(t) } func (o *oldToNewAdapter) GetNext(ctx context.Context) time.Time { return o.delegate.GetNext() } func (o *oldToNewAdapter) SetPrev(ctx context.Context, t time.Time) { o.delegate.SetPrev(t) } func (o *oldToNewAdapter) GetPrev(ctx context.Context) time.Time { return o.delegate.GetPrev() }