feat($task): 任务失败重试间隔时间可由用户自定义, 如果未配置则按默认重试策略执行

Close #30
pull/21/merge
ouqiang 2017-12-09 11:01:48 +08:00
parent 3fd5b2ee55
commit 68d569a6de
5 changed files with 59 additions and 15 deletions

View File

@ -53,11 +53,12 @@ func (migration *Migration) Upgrade(oldVersionId int) {
return return
} }
versionIds := []int{110, 122, 130} versionIds := []int{110, 122, 130, 140}
upgradeFuncs := []func(*xorm.Session) error{ upgradeFuncs := []func(*xorm.Session) error{
migration.upgradeFor110, migration.upgradeFor110,
migration.upgradeFor122, migration.upgradeFor122,
migration.upgradeFor130, migration.upgradeFor130,
migration.upgradeFor140,
} }
startIndex := -1 startIndex := -1
@ -157,7 +158,7 @@ func (migration *Migration) upgradeFor122(session *xorm.Session) error {
return err return err
} }
// 升级到1.2.3版本 // 升级到v1.3版本
func (migration *Migration) upgradeFor130(session *xorm.Session) error { func (migration *Migration) upgradeFor130(session *xorm.Session) error {
logger.Info("开始升级到v1.3") logger.Info("开始升级到v1.3")
@ -167,5 +168,19 @@ func (migration *Migration) upgradeFor130(session *xorm.Session) error {
logger.Info("已升级到v1.3\n") logger.Info("已升级到v1.3\n")
return err
}
// 升级到v1.4版本
func (migration *Migration) upgradeFor140(session *xorm.Session) error {
logger.Info("开始升级到v1.4")
tableName := TablePrefix + "task"
// task表增加字段
// retry_interval 重试间隔时间(秒)
_, err := session.Exec(fmt.Sprintf("ALTER TABLE %s ADD COLUMN retry_interval SMALLINT NOT NULL DEFAULT 0", tableName))
logger.Info("已升级到v1.4\n")
return err return err
} }

View File

@ -32,17 +32,18 @@ const (
type Task struct { type Task struct {
Id int `xorm:"int pk autoincr"` Id int `xorm:"int pk autoincr"`
Name string `xorm:"varchar(32) notnull"` // 任务名称 Name string `xorm:"varchar(32) notnull"` // 任务名称
Level TaskLevel `xorm:"smallint notnull index default 1"` // 任务等级 1: 主任务 2: 依赖任务 Level TaskLevel `xorm:"tinyint notnull index default 1"` // 任务等级 1: 主任务 2: 依赖任务
DependencyTaskId string `xorm:"varchar(64) notnull default ''"` // 依赖任务ID,多个ID逗号分隔 DependencyTaskId string `xorm:"varchar(64) notnull default ''"` // 依赖任务ID,多个ID逗号分隔
DependencyStatus TaskDependencyStatus `xorm:"smallint notnull default 1"` // 依赖关系 1:强依赖 主任务执行成功, 依赖任务才会被执行 2:弱依赖 DependencyStatus TaskDependencyStatus `xorm:"tinyint notnull default 1"` // 依赖关系 1:强依赖 主任务执行成功, 依赖任务才会被执行 2:弱依赖
Spec string `xorm:"varchar(64) notnull"` // crontab Spec string `xorm:"varchar(64) notnull"` // crontab
Protocol TaskProtocol `xorm:"tinyint notnull index"` // 协议 1:http 2:系统命令 Protocol TaskProtocol `xorm:"tinyint notnull index"` // 协议 1:http 2:系统命令
Command string `xorm:"varchar(256) notnull"` // URL地址或shell命令 Command string `xorm:"varchar(256) notnull"` // URL地址或shell命令
Timeout int `xorm:"mediumint notnull default 0"` // 任务执行超时时间(单位秒),0不限制 Timeout int `xorm:"mediumint notnull default 0"` // 任务执行超时时间(单位秒),0不限制
Multi int8 `xorm:"tinyint notnull default 1"` // 是否允许多实例运行 Multi int8 `xorm:"tinyint notnull default 1"` // 是否允许多实例运行
RetryTimes int8 `xorm:"tinyint notnull default 0"` // 重试次数 RetryTimes int8 `xorm:"tinyint notnull default 0"` // 重试次数
NotifyStatus int8 `xorm:"smallint notnull default 1"` // 任务执行结束是否通知 0: 不通知 1: 失败通知 2: 执行结束通知 RetryInterval int16 `xorm:"smallint notnull default 0"` // 重试间隔时间
NotifyType int8 `xorm:"smallint notnull default 0"` // 通知类型 1: 邮件 2: slack NotifyStatus int8 `xorm:"tinyint notnull default 1"` // 任务执行结束是否通知 0: 不通知 1: 失败通知 2: 执行结束通知
NotifyType int8 `xorm:"tinyint notnull default 0"` // 通知类型 1: 邮件 2: slack
NotifyReceiverId string `xorm:"varchar(256) notnull default '' "` // 通知接受者ID, setting表主键ID多个ID逗号分隔 NotifyReceiverId string `xorm:"varchar(256) notnull default '' "` // 通知接受者ID, setting表主键ID多个ID逗号分隔
Tag string `xorm:"varchar(32) notnull default ''"` Tag string `xorm:"varchar(32) notnull default ''"`
Remark string `xorm:"varchar(100) notnull default ''"` // 备注 Remark string `xorm:"varchar(100) notnull default ''"` // 备注
@ -83,7 +84,9 @@ func (task *Task) CreateTestTask() {
func (task *Task) UpdateBean(id int) (int64, error) { func (task *Task) UpdateBean(id int) (int64, error) {
return Db.ID(id). return Db.ID(id).
Cols("name,spec,protocol,command,timeout,multi,retry_times,remark,notify_status,notify_type,notify_receiver_id, dependency_task_id, dependency_status, tag"). Cols("name,spec,protocol,command,timeout,multi," +
"retry_times,retry_interval,remark,notify_status," +
"notify_type,notify_receiver_id, dependency_task_id, dependency_status, tag").
Update(task) Update(task)
} }

View File

@ -28,6 +28,7 @@ type TaskForm struct {
Timeout int `binding:"Range(0,86400)"` Timeout int `binding:"Range(0,86400)"`
Multi int8 `binding:"In(1,2)"` Multi int8 `binding:"In(1,2)"`
RetryTimes int8 RetryTimes int8
RetryInterval int16
HostId string HostId string
Tag string Tag string
Remark string Remark string
@ -135,6 +136,7 @@ func Store(ctx *macaron.Context, form TaskForm) string {
taskModel.Remark = form.Remark taskModel.Remark = form.Remark
taskModel.Multi = form.Multi taskModel.Multi = form.Multi
taskModel.RetryTimes = form.RetryTimes taskModel.RetryTimes = form.RetryTimes
taskModel.RetryInterval = form.RetryInterval
if taskModel.Multi != 1 { if taskModel.Multi != 1 {
taskModel.Multi = 0 taskModel.Multi = 0
} }
@ -162,6 +164,10 @@ func Store(ctx *macaron.Context, form TaskForm) string {
return json.CommonFailure("任务重试次数取值0-10") return json.CommonFailure("任务重试次数取值0-10")
} }
if taskModel.RetryInterval > 3600 || taskModel.RetryInterval < 0 {
return json.CommonFailure("任务重试间隔时间取值0-3600")
}
if taskModel.DependencyStatus != models.TaskDependencyStatusStrong && if taskModel.DependencyStatus != models.TaskDependencyStatusStrong &&
taskModel.DependencyStatus != models.TaskDependencyStatusWeak { taskModel.DependencyStatus != models.TaskDependencyStatusWeak {
return json.CommonFailure("请选择依赖关系") return json.CommonFailure("请选择依赖关系")

View File

@ -404,8 +404,12 @@ func execJob(handler Handler, taskModel models.Task) TaskResult {
i++ i++
if i < execTimes { if i < execTimes {
logger.Warnf("任务执行失败#任务id-%d#重试第%d次#输出-%s#错误-%s", taskModel.Id, i, output, err.Error()) logger.Warnf("任务执行失败#任务id-%d#重试第%d次#输出-%s#错误-%s", taskModel.Id, i, output, err.Error())
// 重试间隔时间每次递增1分钟 if taskModel.RetryInterval > 0 {
time.Sleep(time.Duration(i) * time.Minute) time.Sleep(time.Duration(taskModel.RetryInterval) * time.Second)
} else {
// 默认重试间隔时间每次递增1分钟
time.Sleep(time.Duration(i) * time.Minute)
}
} }
} }

View File

@ -118,15 +118,11 @@
<textarea rows="5" name="command" placeholder="请输入系统命令" id="command">{{{.Task.Command}}}</textarea> <textarea rows="5" name="command" placeholder="请输入系统命令" id="command">{{{.Task.Command}}}</textarea>
</div> </div>
</div> </div>
<div class="three fields"> <div class="two fields">
<div class="field"> <div class="field">
<label>(, 0-86400)</label> <label>(, 0-86400)</label>
<input type="text" name="timeout" placeholder="默认0, 不限制" value="{{{if .Task}}} {{{.Task.Timeout}}} {{{else}}}0{{{end}}}"> <input type="text" name="timeout" placeholder="默认0, 不限制" value="{{{if .Task}}} {{{.Task.Timeout}}} {{{else}}}0{{{end}}}">
</div> </div>
<div class="field">
<label> (0-10)</label>
<input type="text" name="retry_times" placeholder="默认0, 不重试" value="{{{if .Task}}} {{{.Task.RetryTimes}}} {{{else}}}0{{{end}}}">
</div>
<div class="field"> <div class="field">
<label></label> <label></label>
<select name="multi"> <select name="multi">
@ -134,8 +130,19 @@
<option value="1"{{{if .Task}}} {{{if eq .Task.Multi 1}}}selected{{{end}}} {{{end}}}></option> <option value="1"{{{if .Task}}} {{{if eq .Task.Multi 1}}}selected{{{end}}} {{{end}}}></option>
</select> </select>
</div> </div>
</div> </div>
<div class="two fields">
<div class="field">
<label> (0-10)</label>
<input type="text" name="retry_times" placeholder="默认0, 不重试" value="{{{if .Task}}} {{{.Task.RetryTimes}}} {{{else}}}0{{{end}}}">
</div>
<div class="field">
<label> (, 0-3600)</label>
<input type="text" name="retry_interval" placeholder="默认0, 执行默认重试策略" value="{{{if .Task}}} {{{.Task.RetryInterval}}} {{{else}}}0{{{end}}}">
</div>
</div>
<div class="three fields"> <div class="three fields">
<div class="field"> <div class="field">
<label></label> <label></label>
@ -423,6 +430,15 @@
} }
] ]
}, },
retryInterval: {
identifier : 'retry_interval',
rules: [
{
type : 'integer[0..3600]',
prompt : '0-3600'
}
]
},
remark: { remark: {
identifier : 'remark', identifier : 'remark',
rules: [ rules: [