292 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			292 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // 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()
 | ||
| }
 |