mirror of https://github.com/ouqiang/gocron
解析crontab表达式方法, 增加错误返回值
parent
a42542705a
commit
64563ac8d8
|
@ -31,3 +31,4 @@ conf/app.ini
|
|||
conf/ansible_hosts.ini
|
||||
profile/*
|
||||
public/resource/javascript/vue.js
|
||||
gocron
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/ouqiang/gocron/modules/utils"
|
||||
"github.com/ouqiang/gocron/service"
|
||||
"strconv"
|
||||
"github.com/jakecoffman/cron"
|
||||
)
|
||||
|
||||
func Index(ctx *macaron.Context) {
|
||||
|
@ -48,6 +49,10 @@ type TaskForm struct {
|
|||
func Store(ctx *macaron.Context, form TaskForm) string {
|
||||
json := utils.JsonResponse{}
|
||||
taskModel := models.Task{}
|
||||
_, err := cron.Parse(form.Spec)
|
||||
if err != nil {
|
||||
return json.CommonFailure("crontab表达式解析失败", err)
|
||||
}
|
||||
nameExists, err := taskModel.NameExist(form.Name)
|
||||
if err != nil {
|
||||
return json.CommonFailure(utils.FailureContent, err)
|
||||
|
|
|
@ -38,13 +38,14 @@ func (task *Task) Initialize() {
|
|||
func (task *Task) Add(taskModel models.TaskHost) {
|
||||
taskFunc := createHandlerJob(taskModel)
|
||||
if taskFunc == nil {
|
||||
logger.Error("添加任务#不存在的任务协议编号", taskModel.Protocol)
|
||||
logger.Error("创建任务处理Job失败,不支持的任务协议#", taskModel.Protocol)
|
||||
return
|
||||
}
|
||||
|
||||
cronName := strconv.Itoa(taskModel.Id)
|
||||
Cron.RemoveJob(cronName)
|
||||
Cron.AddFunc(taskModel.Spec, taskFunc, cronName)
|
||||
err := Cron.AddFunc(taskModel.Spec, taskFunc, cronName)
|
||||
logger.Error("添加任务到调度器失败#", err)
|
||||
}
|
||||
|
||||
type Handler interface {
|
||||
|
@ -61,7 +62,7 @@ func (h *HTTPHandler) Run(taskModel models.TaskHost) (result string, err error)
|
|||
}
|
||||
req, err := http.NewRequest("POST", taskModel.Command, nil)
|
||||
if err != nil {
|
||||
logger.Error("创建HTTP请求错误-", err.Error())
|
||||
logger.Error("任务处理#创建HTTP请求错误-", err.Error())
|
||||
return
|
||||
}
|
||||
req.Header.Set("Content-type", "application/x-www-form-urlencoded")
|
||||
|
@ -74,12 +75,12 @@ func (h *HTTPHandler) Run(taskModel models.TaskHost) (result string, err error)
|
|||
}
|
||||
}()
|
||||
if err != nil {
|
||||
logger.Error("HTTP请求错误-", err.Error())
|
||||
logger.Error("任务处理HTTP请求错误-", err.Error())
|
||||
return
|
||||
}
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
logger.Error("读取HTTP请求返回值失败-", err.Error())
|
||||
logger.Error("任务处理#读取HTTP请求返回值失败-", err.Error())
|
||||
}
|
||||
|
||||
return string(body), err
|
||||
|
@ -145,7 +146,7 @@ func createHandlerJob(taskModel models.TaskHost) cron.FuncJob {
|
|||
taskFunc := func() {
|
||||
taskLogId, err := createTaskLog(taskModel)
|
||||
if err != nil {
|
||||
logger.Error("写入任务日志失败-", err)
|
||||
logger.Error("任务开始执行#写入任务日志失败-", err)
|
||||
return
|
||||
}
|
||||
// err != nil 执行失败, 失败重试3次
|
||||
|
@ -156,12 +157,12 @@ func createHandlerJob(taskModel models.TaskHost) cron.FuncJob {
|
|||
if err == nil {
|
||||
break
|
||||
} else {
|
||||
logger.Error("执行失败#tasklog.id-" + strconv.FormatInt(taskLogId, 10) + "#尝试次数-" + strconv.Itoa(i + 1) + "#" + err.Error() + " " + result)
|
||||
logger.Error("任务执行失败#tasklog.id-" + strconv.FormatInt(taskLogId, 10) + "#尝试次数-" + strconv.Itoa(i + 1) + "#" + err.Error() + " " + result)
|
||||
}
|
||||
}
|
||||
_, err = updateTaskLog(taskLogId, result, err)
|
||||
if err != nil {
|
||||
logger.Error("更新任务日志失败-", err)
|
||||
logger.Error("任务结束#更新任务日志失败-", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -90,13 +90,18 @@ type FuncJob func()
|
|||
func (f FuncJob) Run() { f() }
|
||||
|
||||
// AddFunc adds a func to the Cron to be run on the given schedule.
|
||||
func (c *Cron) AddFunc(spec string, cmd func(), name string) {
|
||||
c.AddJob(spec, FuncJob(cmd), name)
|
||||
func (c *Cron) AddFunc(spec string, cmd func(), name string) error {
|
||||
return c.AddJob(spec, FuncJob(cmd), name)
|
||||
}
|
||||
|
||||
// AddFunc adds a Job to the Cron to be run on the given schedule.
|
||||
func (c *Cron) AddJob(spec string, cmd Job, name string) {
|
||||
c.Schedule(Parse(spec), cmd, name)
|
||||
func (c *Cron) AddJob(spec string, cmd Job, name string) error {
|
||||
schedule, err := Parse(spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Schedule(schedule, cmd, name)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveJob removes a Job from the Cron based on name.
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Parse returns a new crontab schedule representing the given spec.
|
||||
|
@ -14,7 +15,10 @@ import (
|
|||
// It accepts
|
||||
// - Full crontab specs, e.g. "* * * * * ?"
|
||||
// - Descriptors, e.g. "@midnight", "@every 1h30m"
|
||||
func Parse(spec string) Schedule {
|
||||
func Parse(spec string) (Schedule, error) {
|
||||
if len(spec) == 0 {
|
||||
return nil, fmt.Errorf("Empty spec string")
|
||||
}
|
||||
if spec[0] == '@' {
|
||||
return parseDescriptor(spec)
|
||||
}
|
||||
|
@ -23,7 +27,7 @@ func Parse(spec string) Schedule {
|
|||
// (second) (minute) (hour) (day of month) (month) (day of week, optional)
|
||||
fields := strings.Fields(spec)
|
||||
if len(fields) != 5 && len(fields) != 6 {
|
||||
log.Panicf("Expected 5 or 6 fields, found %d: %s", len(fields), spec)
|
||||
return nil, fmt.Errorf("Expected 5 or 6 fields, found %d: %s", len(fields), spec)
|
||||
}
|
||||
|
||||
// If a sixth field is not provided (DayOfWeek), then it is equivalent to star.
|
||||
|
@ -40,7 +44,7 @@ func Parse(spec string) Schedule {
|
|||
Dow: getField(fields[5], dow),
|
||||
}
|
||||
|
||||
return schedule
|
||||
return schedule, nil
|
||||
}
|
||||
|
||||
// getField returns an Int with the bits set representing all of the times that
|
||||
|
@ -156,7 +160,7 @@ func all(r bounds) uint64 {
|
|||
|
||||
// parseDescriptor returns a pre-defined schedule for the expression, or panics
|
||||
// if none matches.
|
||||
func parseDescriptor(spec string) Schedule {
|
||||
func parseDescriptor(spec string) (Schedule,error) {
|
||||
switch spec {
|
||||
case "@yearly", "@annually":
|
||||
return &SpecSchedule{
|
||||
|
@ -166,7 +170,7 @@ func parseDescriptor(spec string) Schedule {
|
|||
Dom: 1 << dom.min,
|
||||
Month: 1 << months.min,
|
||||
Dow: all(dow),
|
||||
}
|
||||
}, nil
|
||||
|
||||
case "@monthly":
|
||||
return &SpecSchedule{
|
||||
|
@ -176,7 +180,7 @@ func parseDescriptor(spec string) Schedule {
|
|||
Dom: 1 << dom.min,
|
||||
Month: all(months),
|
||||
Dow: all(dow),
|
||||
}
|
||||
}, nil
|
||||
|
||||
case "@weekly":
|
||||
return &SpecSchedule{
|
||||
|
@ -186,7 +190,7 @@ func parseDescriptor(spec string) Schedule {
|
|||
Dom: all(dom),
|
||||
Month: all(months),
|
||||
Dow: 1 << dow.min,
|
||||
}
|
||||
}, nil
|
||||
|
||||
case "@daily", "@midnight":
|
||||
return &SpecSchedule{
|
||||
|
@ -196,7 +200,7 @@ func parseDescriptor(spec string) Schedule {
|
|||
Dom: all(dom),
|
||||
Month: all(months),
|
||||
Dow: all(dow),
|
||||
}
|
||||
}, nil
|
||||
|
||||
case "@hourly":
|
||||
return &SpecSchedule{
|
||||
|
@ -206,18 +210,17 @@ func parseDescriptor(spec string) Schedule {
|
|||
Dom: all(dom),
|
||||
Month: all(months),
|
||||
Dow: all(dow),
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
const every = "@every "
|
||||
if strings.HasPrefix(spec, every) {
|
||||
duration, err := time.ParseDuration(spec[len(every):])
|
||||
if err != nil {
|
||||
log.Panicf("Failed to parse duration %s: %s", spec, err)
|
||||
}
|
||||
return Every(duration)
|
||||
return nil, fmt.Errorf("Failed to parse duration %s: %s", spec, err)
|
||||
}
|
||||
return Every(duration),nil
|
||||
}
|
||||
|
||||
log.Panicf("Unrecognized descriptor: %s", spec)
|
||||
return nil
|
||||
return nil, fmt.Errorf("Unrecognized descriptor: %s", spec)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue