解析crontab表达式方法, 增加错误返回值

pull/21/merge
ouqiang 2017-04-13 21:54:13 +08:00
parent a42542705a
commit 64563ac8d8
5 changed files with 41 additions and 26 deletions

1
.gitignore vendored
View File

@ -31,3 +31,4 @@ conf/app.ini
conf/ansible_hosts.ini
profile/*
public/resource/javascript/vue.js
gocron

View File

@ -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)

View File

@ -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)
}
}

View File

@ -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.

View File

@ -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)
}