1. 优化 JobHandlerInvoker 的实现,增加重试机制

2. 去除作业异常,自动暂时作业的机制。
This commit is contained in:
YunaiV
2021-02-18 21:26:59 +08:00
parent a4a13efa4a
commit 3959aadae2
30 changed files with 1019 additions and 1017 deletions

View File

@@ -1,4 +1,4 @@
package cn.iocoder.dashboard.modules.infra.controller.dbdoc;
package cn.iocoder.dashboard.modules.infra.controller.doc;
import cn.hutool.extra.servlet.ServletUtil;
import cn.smallbun.screw.core.Configuration;

View File

@@ -23,6 +23,14 @@ public class InfJobBaseVO {
@NotNull(message = "CRON 表达式不能为空")
private String cronExpression;
@ApiModelProperty(value = "重试次数", required = true)
@NotNull(message = "重试次数不能为空")
private Integer retryCount;
@ApiModelProperty(value = "重试间隔", required = true)
@NotNull(message = "重试间隔不能为空")
private Integer retryInterval;
@ApiModelProperty(value = "监控超时时间", example = "1000")
private Integer monitorTimeout;

View File

@@ -0,0 +1,53 @@
package cn.iocoder.dashboard.modules.infra.controller.job.vo.log;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.util.Date;
import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 定时任务日志 Base VO提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class InfJobLogBaseVO {
@ApiModelProperty(value = "任务编号", required = true)
@NotNull(message = "任务编号不能为空")
private Long jobId;
@ApiModelProperty(value = "处理器的名字", required = true)
@NotNull(message = "处理器的名字不能为空")
private String handlerName;
@ApiModelProperty(value = "处理器的参数")
private String handlerParam;
@ApiModelProperty(value = "第几次执行", required = true)
@NotNull(message = "第几次执行不能为空")
private Integer executeIndex;
@ApiModelProperty(value = "开始执行时间", required = true)
@NotNull(message = "开始执行时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date beginTime;
@ApiModelProperty(value = "结束执行时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private Date endTime;
@ApiModelProperty(value = "执行时长")
private Integer duration;
@ApiModelProperty(value = "任务状态", required = true)
@NotNull(message = "任务状态不能为空")
private Integer status;
@ApiModelProperty(value = "结果数据")
private String result;
}

View File

@@ -0,0 +1,49 @@
package cn.iocoder.dashboard.modules.infra.controller.job.vo.log;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
/**
* 定时任务 Excel VO
*
* @author 芋艿
*/
@Data
public class InfJobLogExcelVO {
@ExcelProperty("日志编号")
private Long id;
@ExcelProperty("任务编号")
private Long jobId;
@ExcelProperty("处理器的名字")
private String handlerName;
@ExcelProperty("处理器的参数")
private String handlerParam;
@ExcelProperty("第几次执行")
private Integer executeIndex;
@ExcelProperty("开始执行时间")
private Date beginTime;
@ExcelProperty("结束执行时间")
private Date endTime;
@ExcelProperty("执行时长")
private Integer duration;
@ExcelProperty("任务状态")
private Integer status;
@ExcelProperty("结果数据")
private String result;
@ExcelProperty("创建时间")
private Date createTime;
}

View File

@@ -0,0 +1,30 @@
package cn.iocoder.dashboard.modules.infra.controller.job.vo.log;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel(value = "定时任务 Excel 导出 Request VO", description = "参数和 InfJobLogPageReqVO 是一致的")
@Data
public class InfJobLogExportReqVO {
@ApiModelProperty(value = "处理器的名字")
private String handlerName;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始执行时间")
private Date beginTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束执行时间")
private Date endTime;
@ApiModelProperty(value = "任务状态")
private Integer status;
}

View File

@@ -0,0 +1,35 @@
package cn.iocoder.dashboard.modules.infra.controller.job.vo.log;
import cn.iocoder.dashboard.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("定时任务日志分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InfJobLogPageReqVO extends PageParam {
@ApiModelProperty(value = "处理器的名字")
private String handlerName;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "开始执行时间")
private Date beginTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "结束执行时间")
private Date endTime;
@ApiModelProperty(value = "任务状态")
private Integer status;
}

View File

@@ -0,0 +1,23 @@
package cn.iocoder.dashboard.modules.infra.controller.job.vo.log;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
@ApiModel("定时任务日志 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InfJobLogRespVO extends InfJobLogBaseVO {
@ApiModelProperty(value = "日志编号", required = true)
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@@ -75,6 +75,18 @@ public class InfJobDO extends BaseDO {
*/
private Date fireNextTime;
// ========== 重试相关字段 ==========
/**
* 重试次数
* 如果不重试,则设置为 0
*/
private Integer retryCount;
/**
* 重试间隔,单位:毫秒
* 如果没有间隔,则设置为 0
*/
private Integer retryInterval;
// ========== 监控相关字段 ==========
/**
* 监控超时时间,单位:毫秒

View File

@@ -44,6 +44,12 @@ public class InfJobLogDO extends BaseDO {
* 冗余字段 {@link InfJobDO#getHandlerParam()}
*/
private String handlerParam;
/**
* 第几次执行
*
* 用于区分是不是重试执行。如果是重试执行,则 index 大于 1
*/
private Integer executeIndex;
/**
* 开始执行时间

View File

@@ -23,17 +23,13 @@ public enum InfJobStatusEnum {
*/
INIT(0, Collections.emptySet()),
/**
* 开启运行
* 开启
*/
NORMAL(1, Sets.newHashSet(STATE_WAITING, STATE_ACQUIRED, STATE_BLOCKED)),
/**
* 异常运行
* 暂停
*/
EXCEPTION(2, Sets.newHashSet(STATE_COMPLETE)),
/**
* 暂停运行
*/
STOP(3, Sets.newHashSet(STATE_PAUSED, STATE_PAUSED_BLOCKED));
STOP(2, Sets.newHashSet(STATE_PAUSED, STATE_PAUSED_BLOCKED));
/**
* 状态

View File

@@ -26,8 +26,8 @@ public class InfJobLogServiceImpl implements InfJobLogService {
private InfJobLogMapper jobLogMapper;
@Override
public Long createJobLog(Long jobId, Date beginTime, String jobHandlerName, String jobHandlerParam) {
InfJobLogDO log = InfJobLogDO.builder().jobId(jobId).handlerName(jobHandlerName).handlerParam(jobHandlerParam)
public Long createJobLog(Long jobId, Date beginTime, String jobHandlerName, String jobHandlerParam, Integer executeIndex) {
InfJobLogDO log = InfJobLogDO.builder().jobId(jobId).handlerName(jobHandlerName).handlerParam(jobHandlerParam).executeIndex(executeIndex)
.beginTime(beginTime).status(InfJobLogStatusEnum.RUNNING.getStatus()).build();
jobLogMapper.insert(log);
return log.getId();
@@ -35,24 +35,14 @@ public class InfJobLogServiceImpl implements InfJobLogService {
@Override
@Async
public void updateJobLogSuccessAsync(Long logId, Date endTime, Integer duration, String result) {
updateJobLogResult(logId, endTime, duration, result, InfJobLogStatusEnum.SUCCESS);
}
@Override
@Async
public void updateJobLogErrorAsync(Long logId, Date endTime, Integer duration, String result) {
updateJobLogResult(logId, endTime, duration, result, InfJobLogStatusEnum.FAILURE);
}
private void updateJobLogResult(Long logId, Date endTime, Integer duration, String result, InfJobLogStatusEnum status) {
public void updateJobLogResultAsync(Long logId, Date endTime, Integer duration, boolean success, String result) {
try {
InfJobLogDO updateObj = InfJobLogDO.builder().id(logId).endTime(endTime).duration(duration)
.status(status.getStatus()).result(result).build();
.status(success ? InfJobLogStatusEnum.SUCCESS.getStatus() : InfJobLogStatusEnum.FAILURE.getStatus()).result(result).build();
jobLogMapper.updateById(updateObj);
} catch (Exception ex) {
log.error("[updateJobLogResult][logId({}) endTime({}) duration({}) result({}) status({})]",
logId, endTime, duration, result, status);
log.error("[updateJobLogResultAsync][logId({}) endTime({}) duration({}) success({}) result({})]",
logId, endTime, duration, success, result);
}
}

View File

@@ -55,7 +55,8 @@ public class InfJobServiceImpl implements InfJobService {
jobMapper.insert(job);
// 添加 Job 到 Quartz 中
schedulerManager.addJob(job.getId(), job.getHandlerName(), job.getHandlerParam(), job.getCronExpression());
schedulerManager.addJob(job.getId(), job.getHandlerName(), job.getHandlerParam(), job.getCronExpression(),
createReqVO.getRetryCount(), createReqVO.getRetryInterval());
// 更新
InfJobDO updateObj = InfJobDO.builder().id(job.getId()).status(InfJobStatusEnum.NORMAL.getStatus()).build();
jobMapper.updateById(updateObj);
@@ -80,7 +81,8 @@ public class InfJobServiceImpl implements InfJobService {
jobMapper.updateById(updateObj);
// 更新 Job 到 Quartz 中
schedulerManager.updateJob(job.getHandlerName(), updateReqVO.getHandlerParam(), updateReqVO.getCronExpression());
schedulerManager.updateJob(job.getHandlerName(), updateReqVO.getHandlerParam(), updateReqVO.getCronExpression(),
updateReqVO.getRetryCount(), updateReqVO.getRetryInterval());
}
@Override
@@ -138,7 +140,7 @@ public class InfJobServiceImpl implements InfJobService {
}
private void validateCronExpression(String cronExpression) {
if (CronUtils.isValid(cronExpression)) {
if (!CronUtils.isValid(cronExpression)) {
throw exception(JOB_CRON_EXPRESSION_VALID);
}
}

View File

@@ -15,6 +15,9 @@ public class SysUserSessionTimeoutJob implements JobHandler {
@Override
public String execute(String param) throws Exception {
if (true) {
throw new RuntimeException("测试异常");
}
// System.out.println("执行了一次任务");
log.info("[execute][执行任务:{}]", param);
return null;

View File

@@ -134,6 +134,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService {
}
@Override
@Transactional
public void syncCodegenFromDB(Long tableId) {
// 校验是否已经存在
ToolCodegenTableDO table = codegenTableMapper.selectById(tableId);
@@ -148,6 +149,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService {
}
@Override
@Transactional
public void syncCodegenFromSQL(Long tableId, String sql) {
// 校验是否已经存在
ToolCodegenTableDO table = codegenTableMapper.selectById(tableId);
@@ -193,7 +195,9 @@ public class ToolCodegenServiceImpl implements ToolCodegenService {
codegenColumnMapper.insert(column); // TODO 批量插入
});
// 删除不存在的字段
codegenColumnMapper.deleteBatchIds(deleteColumnIds);
if (CollUtil.isNotEmpty(deleteColumnIds)) {
codegenColumnMapper.deleteBatchIds(deleteColumnIds);
}
}
@Override