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
}
versionIds := []int{110, 122, 130}
versionIds := []int{110, 122, 130, 140}
upgradeFuncs := []func(*xorm.Session) error{
migration.upgradeFor110,
migration.upgradeFor122,
migration.upgradeFor130,
migration.upgradeFor140,
}
startIndex := -1
@ -157,7 +158,7 @@ func (migration *Migration) upgradeFor122(session *xorm.Session) error {
return err
}
// 升级到1.2.3版本
// 升级到v1.3版本
func (migration *Migration) upgradeFor130(session *xorm.Session) error {
logger.Info("开始升级到v1.3")
@ -167,5 +168,19 @@ func (migration *Migration) upgradeFor130(session *xorm.Session) error {
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
}

View File

@ -32,17 +32,18 @@ const (
type Task struct {
Id int `xorm:"int pk autoincr"`
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逗号分隔
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
Protocol TaskProtocol `xorm:"tinyint notnull index"` // 协议 1:http 2:系统命令
Command string `xorm:"varchar(256) notnull"` // URL地址或shell命令
Timeout int `xorm:"mediumint notnull default 0"` // 任务执行超时时间(单位秒),0不限制
Multi int8 `xorm:"tinyint notnull default 1"` // 是否允许多实例运行
RetryTimes int8 `xorm:"tinyint notnull default 0"` // 重试次数
NotifyStatus int8 `xorm:"smallint notnull default 1"` // 任务执行结束是否通知 0: 不通知 1: 失败通知 2: 执行结束通知
NotifyType int8 `xorm:"smallint notnull default 0"` // 通知类型 1: 邮件 2: slack
RetryInterval int16 `xorm:"smallint notnull default 0"` // 重试间隔时间
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逗号分隔
Tag string `xorm:"varchar(32) 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) {
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)
}

View File

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

View File

@ -404,8 +404,12 @@ func execJob(handler Handler, taskModel models.Task) TaskResult {
i++
if i < execTimes {
logger.Warnf("任务执行失败#任务id-%d#重试第%d次#输出-%s#错误-%s", taskModel.Id, i, output, err.Error())
// 重试间隔时间每次递增1分钟
time.Sleep(time.Duration(i) * time.Minute)
if taskModel.RetryInterval > 0 {
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>
</div>
</div>
<div class="three fields">
<div class="two fields">
<div class="field">
<label>(, 0-86400)</label>
<input type="text" name="timeout" placeholder="默认0, 不限制" value="{{{if .Task}}} {{{.Task.Timeout}}} {{{else}}}0{{{end}}}">
</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">
<label></label>
<select name="multi">
@ -134,8 +130,19 @@
<option value="1"{{{if .Task}}} {{{if eq .Task.Multi 1}}}selected{{{end}}} {{{end}}}></option>
</select>
</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="field">
<label></label>
@ -423,6 +430,15 @@
}
]
},
retryInterval: {
identifier : 'retry_interval',
rules: [
{
type : 'integer[0..3600]',
prompt : '0-3600'
}
]
},
remark: {
identifier : 'remark',
rules: [