287 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			287 lines
		
	
	
		
			7.0 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/pkg/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)
 | 
						||
}
 | 
						||
 | 
						||
// 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()
 | 
						||
}
 |