1. 优化 JobHandlerInvoker 的实现,增加重试机制
2. 去除作业异常,自动暂时作业的机制。
This commit is contained in:
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -75,6 +75,18 @@ public class InfJobDO extends BaseDO {
|
||||
*/
|
||||
private Date fireNextTime;
|
||||
|
||||
// ========== 重试相关字段 ==========
|
||||
/**
|
||||
* 重试次数
|
||||
* 如果不重试,则设置为 0
|
||||
*/
|
||||
private Integer retryCount;
|
||||
/**
|
||||
* 重试间隔,单位:毫秒
|
||||
* 如果没有间隔,则设置为 0
|
||||
*/
|
||||
private Integer retryInterval;
|
||||
|
||||
// ========== 监控相关字段 ==========
|
||||
/**
|
||||
* 监控超时时间,单位:毫秒
|
||||
|
||||
@@ -44,6 +44,12 @@ public class InfJobLogDO extends BaseDO {
|
||||
* 冗余字段 {@link InfJobDO#getHandlerParam()}
|
||||
*/
|
||||
private String handlerParam;
|
||||
/**
|
||||
* 第几次执行
|
||||
*
|
||||
* 用于区分是不是重试执行。如果是重试执行,则 index 大于 1
|
||||
*/
|
||||
private Integer executeIndex;
|
||||
|
||||
/**
|
||||
* 开始执行时间
|
||||
|
||||
@@ -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));
|
||||
|
||||
/**
|
||||
* 状态
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user