gf/g/os/gcron/gcron_entry.go

130 lines
4.2 KiB
Go

// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gcron
import (
"github.com/gogf/gf/g/os/glog"
"github.com/gogf/gf/g/os/gtimer"
"github.com/gogf/gf/g/util/gconv"
"reflect"
"runtime"
"time"
)
// Timed task entry.
type Entry struct {
cron *Cron // Cron object belonged to.
entry *gtimer.Entry // Associated gtimer.Entry.
schedule *cronSchedule // Timed schedule object.
jobName string // Callback function name(address info).
Name string // Entry name.
Job func() `json:"-"` // Callback function.
Time time.Time // Registered time.
}
// addEntry creates and returns a new Entry object.
// Param <job> is the callback function for timed task execution.
// Param <singleton> specifies whether timed task executing in singleton mode.
// Param <times> limits the times for timed task executing.
// Param <name> names this entry for manual control.
func (c *Cron) addEntry(pattern string, job func(), singleton bool, times int, name ... string) (*Entry, error) {
schedule, err := newSchedule(pattern)
if err != nil {
return nil, err
}
entry := &Entry {
cron : c,
schedule : schedule,
jobName : runtime.FuncForPC(reflect.ValueOf(job).Pointer()).Name(),
Job : job,
Time : time.Now(),
}
if len(name) > 0 {
entry.Name = name[0]
} else {
entry.Name = "gcron-" + gconv.String(c.idGen.Add(1))
}
entry.entry = gtimer.AddEntry(time.Second, entry.check, singleton, times, gtimer.STATUS_STOPPED)
entry.entry.Start()
c.entries.Set(entry.Name, entry)
return entry, nil
}
// 是否单例运行
func (entry *Entry) IsSingleton() bool {
return entry.entry.IsSingleton()
}
// 设置单例运行
func (entry *Entry) SetSingleton(enabled bool) {
entry.entry.SetSingleton(true)
}
// 设置任务的运行次数
func (entry *Entry) SetTimes(times int) {
entry.entry.SetTimes(times)
}
// 定时任务状态
func (entry *Entry) Status() int {
return entry.entry.Status()
}
// 设置定时任务状态, 返回设置之前的状态
func (entry *Entry) SetStatus(status int) int {
return entry.entry.SetStatus(status)
}
// 启动定时任务
func (entry *Entry) Start() {
entry.entry.Start()
}
// 停止定时任务
func (entry *Entry) Stop() {
entry.entry.Stop()
}
// 关闭定时任务
func (entry *Entry) Close() {
entry.cron.entries.Remove(entry.Name)
entry.entry.Close()
}
// 定时任务检查执行
func (entry *Entry) check() {
if entry.schedule.meet(time.Now()) {
path := entry.cron.GetLogPath()
level := entry.cron.GetLogLevel()
// 检查定时任务对象状态(非任务状态)
switch entry.cron.status.Val() {
case STATUS_STOPPED:
return
case STATUS_CLOSED:
entry.cron.Remove(entry.Name)
glog.Path(path).Level(level).Debugfln("[gcron] %s(%s) %s remove", entry.Name, entry.schedule.pattern, entry.jobName)
gtimer.Exit()
case STATUS_READY: fallthrough
case STATUS_RUNNING:
glog.Path(path).Level(level).Debugfln("[gcron] %s(%s) %s start", entry.Name, entry.schedule.pattern, entry.jobName)
defer func() {
if entry.entry.Status() == STATUS_CLOSED {
entry.cron.Remove(entry.Name)
}
if err := recover(); err != nil {
glog.Path(path).Level(level).Errorfln("[gcron] %s(%s) %s end with error: %v", entry.Name, entry.schedule.pattern, entry.jobName, err)
} else {
glog.Path(path).Level(level).Debugfln("[gcron] %s(%s) %s end", entry.Name, entry.schedule.pattern, entry.jobName)
}
}()
entry.Job()
}
}
}