一、改造背景
因为目前xxl-job 不支持子任务并行执行,所以通过新增几张表来控制任务的父子关系和子任务的并行处理
二、表设计
TD_WORKTASK
表名:工作任务信息表,用于存储所有的任务信息列表
序号
|
字段名称
|
字段类型
|
字段描述
|
1
|
S_TASKNO
|
String
|
任务编号
|
2
|
S_TASKCMT
|
String
|
任务说明
|
3
|
S_TASKFLOWNO
|
String
|
任务流编号
|
4
|
S_FRONTTASKNOLIST
|
String
|
前置任务编号列表(暂不使用)
|
5
|
S_FRONTTASKFLOWNO
|
String
|
前置任务流编号(暂不使用)
|
TD_WORKTASKFLOW表
表名:工作任务流信息表,用于存储所有的任务流列表
序号
|
字段名称
|
字段类型
|
字段描述
|
1
|
S_TASKFLOWNO
|
String
|
任务流编号
|
2
|
S_TASKFLOWCMT
|
String
|
任务流说明
|
3
|
I_SUBTASKNUM
|
String
|
子任务数目
|
4
|
I_TASKSEQ
|
String
|
任务顺序
|
5
|
S_FRONTTASKFLOWNO
|
String
|
前置任务流编号
|
TD_WORKTASKTRC表
表名:工作任务流跟踪表,用于存储每日所有的任务执行情况
序号
|
字段名称
|
字段类型
|
字段描述
|
1
|
D_TASKDATE
|
DATE
|
任务日期
|
2
|
S_TASKNO
|
String
|
任务编号
|
3
|
S_TABNAME
|
String
|
表名
|
4
|
S_TASKCMT
|
String
|
任务说明
|
5
|
S_TASKFLOWNO
|
String
|
任务流编号
|
6
|
S_FRONTTASKNOLIST
|
String
|
前置任务编号列表
|
7
|
S_FRONTTASKFLOWNO
|
String
|
前置任务流编号
|
8
|
S_RUNSTATE
|
String
|
执行状态
|
9
|
S_ISFINISHED
|
String
|
是否已完成
|
10
|
S_ERRDESC
|
String
|
错误描述
|
11
|
S_BUSTYPE
|
String
|
业务类型
|
12
|
I_PARAMSEQNO
|
int
|
参数序号
|
13
|
TS_SYSUPDATE
|
Timestamp
|
系统更新时间
|
TD_WORKTASKFLOWTRC表
工作任务流跟踪表,用于存储每日所有的任务执行情况
序号
|
字段名称
|
字段类型
|
字段描述
|
1
|
D_TASKDATE
|
DATE
|
任务日期
|
2
|
S_TASKFLOWNO
|
String
|
任务流编号
|
3
|
S_TASKFLOWCMT
|
String
|
任务流说明
|
4
|
I_SUBTASKNUM
|
int
|
子任务数目
|
5
|
I_FINISHSUBTASKNUM
|
int
|
已完成子任务数目
|
6
|
I_TASKSEQ
|
int
|
任务顺序
|
7
|
S_FRONTTASKFLOWNO
|
String
|
前置任务流编号
|
8
|
S_RUNSTATE
|
String
|
执行状态
|
9
|
S_ISFINISHED
|
String
|
是否已完成
|
10
|
TS_SYSUPDATE
|
TimeStamp
|
系统更新时间
|
TD_BPBASE表
表名:批处理基础数据信息表,用于存储所有的任务执行参数信息
序号
|
字段名称
|
字段类型
|
字段描述
|
1
|
S_TASKNO
|
String
|
任务编号
|
2
|
S_OFSYS
|
String
|
所属系统
|
3
|
S_FILENAME
|
String
|
文件名称
|
4
|
S_FILEFORMAT
|
String
|
文件格式
|
5
|
S_FILEPATH
|
String
|
文件路径
|
6
|
S_ISCOMPRESS
|
String
|
是否解压缩
|
7
|
S_COMPRESSFORMAT
|
String
|
压缩格式
|
8
|
S_COMPRESSAFTERNAME
|
String
|
解压后文件名称
|
9
|
S_ORITBLNAME
|
String
|
源表名称
|
10
|
S_ORITBLSCHEMA
|
String
|
源表schema
|
11
|
S_ORITBLDESC
|
String
|
原表表名
|
12
|
S_TARTBLNAME
|
String
|
目标表名称
|
13
|
S_TARTBLSCHEMA
|
String
|
目标表schema
|
14
|
S_ISBACKUP
|
String
|
是否保留
|
15
|
S_ISLOAD
|
String
|
是否导入
|
16
|
S_ISEXTRACT
|
String
|
是否抽取到批处理层
|
17
|
S_ISCLEAN
|
String
|
是否清理
|
18
|
S_CLEANWHERE
|
String
|
清理条件
|
19
|
S_ISPUSH
|
String
|
是否推送至tdh
|
20
|
S_PUSHWHERE
|
String
|
推送条件
|
21
|
S_PUSHMODE
|
String
|
推送模式
|
22
|
S_ISBUSPARAMEFFECT
|
String
|
是否是业务参数生效
|
23
|
S_PPD1
|
String
|
预留字段1
|
24
|
S_PPD2
|
String
|
预留字段2
|
25
|
S_PPD3
|
String
|
预留字段3
|
TS_SYS_STATUS表
表名:系统状态表
序号
|
字段名称
|
字段类型
|
字段描述
|
1
|
I_SEQNO
|
Long
|
序列号
|
2
|
D_CURACCT
|
DATE
|
当前账务日期
|
3
|
D_NATURAL
|
DATE
|
自然日期
|
4
|
S_SYSSTATE
|
String
|
系统状态
|
5
|
S_CTRSTATE
|
String
|
点名状态
|
6
|
S_ARCHSTATE
|
String
|
归档状态
|
7
|
S_FILEARCHSTATE
|
String
|
登记簿归档状态
|
8
|
S_SYSREMARK
|
String
|
系统状态备注
|
9
|
TS_SYSUPDATE
|
Timestamp
|
系统更新时间
|
建表语句
DROP TABLE TD_WORKTASK;
CREATE TABLE `TD_WORKTASK` (
`S_TASKNO` VARCHAR(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务编号',
`S_TASKCMT` VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务说明',
`S_TASKFLOWNO` VARCHAR(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务流编号',
`S_FRONTTASKNOLIST` VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '前置任务编号列表',
`S_FRONTTASKFLOWNO` VARCHAR(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '前置任务流编号',
PRIMARY KEY (`S_TASKNO`) USING BTREE
) ENGINE=INNODB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='工作任务信息表'
DROP TABLE TD_WORKTASKFLOW;
CREATE TABLE `TD_WORKTASKFLOW` (
`S_TASKFLOWNO` VARCHAR(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务流编号',
`S_TASKFLOWCMT` VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务流说明',
`I_SUBTASKNUM` INT(32) NOT NULL COMMENT '子任务数目',
`I_TASKSEQ` INT(8) DEFAULT NULL COMMENT '任务顺序',
`S_FRONTTASKFLOWNO` VARCHAR(30) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '前置任务流编号'
) ENGINE=INNODB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='工作任务流信息表'
DROP TABLE TD_WORKTASKFLOWTRC;
CREATE TABLE `TD_WORKTASKFLOWTRC` (
`D_TASKDATE` DATE NOT NULL COMMENT '任务日期',
`S_TASKFLOWNO` VARCHAR(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务流编号',
`S_TASKFLOWCMT` VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务流说明',
`I_SUBTASKNUM` INT(32) NOT NULL COMMENT '子任务数目',
`I_TASKSEQ` INT(8) DEFAULT NULL COMMENT '任务顺序',
`S_FRONTTASKFLOWNO` VARCHAR(30) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '前置任务流编号',
`S_RUNSTATE` TINYINT(1) COMMENT '执行状态',
`S_ISFINISHED` TINYINT(1) COMMENT '是否已完成',
`TS_SYSUPDATE` DATETIME COMMENT '系统更新时间'
) ENGINE=INNODB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='工作任务流跟踪表'
DROP TABLE TD_WORKTASKTRC;
CREATE TABLE `TD_WORKTASKTRC` (
`D_TASKDATE` DATE NOT NULL COMMENT '任务日期',
`S_TASKNO` VARCHAR(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务编号',
`S_TABNAME` VARCHAR(40) CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT '表名',
`S_TASKCMT` VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT '任务说明',
`S_TASKFLOWNO` VARCHAR(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务流编号',
`S_FRONTTASKNOLIST` VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '前置任务编号列表',
`S_FRONTTASKFLOWNO` VARCHAR(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '前置任务流编号',
`S_RUNSTATE` TINYINT(1) COMMENT '执行状态',
`S_ISFINISHED` TINYINT(1) COMMENT '是否已完成',
`S_ERRDESC` VARCHAR(2048) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '错误描述',
`S_BUSTYPE` VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '业务类型',
`I_PARAMSEQNO` int(32) COMMENT '参数序号',
`TS_SYSUPDATE` DATE COMMENT '系统更新时间'
) ENGINE=INNODB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='工作任务跟踪表'
三、任务流程设计
四、核心代码设计
任务流及任务表处理的核心方法
/**
* @Description:查询当前工作日期
* @Param: []
* @Teturn: java.util.Date
* @Date: Created in 2018/11/13 10:13
*/
public Date queryCurrentDateWork(){
Date date = null;
try {
TsSysStatus t = new TsSysStatus();
TsSysStatus dto = tsSysstatusMapper.selectOne(t);
date = dto.getdCuracct();
} catch (Exception e) {
log.error("查询当前工作日期异常",e);
}
return date;
}
/**
* @Description:
* @Param: [date, sTaskflowno]
* @Teturn: boolean
* @Date: Created in 2019/1/8 9:22
*/
public boolean doPrepareForTaskFlow(Date date,String sTaskflowno) throws Exception{
try {
//1.判断此任务流状态
TdWorktaskflowtrc t = new TdWorktaskflowtrc();
t.setdTaskdate(date);
t.setsTaskflowno(sTaskflowno);
TdWorktaskflowtrc runStateDto = tdWorktaskflowtrcMapper.selectOne(t);
if(runStateDto==null){
XxlJobLogger.log("根据任务日期:["+date+"],任务流编号:["+sTaskflowno+"],无法查询到相应任务流!");
throw new RuntimeException("根据任务日期:["+date+"],任务流编号:["+sTaskflowno+"],无法查询到相应任务流!");
}
String sRunState = runStateDto.getsRunstate();
//当任务流状态是已执行状态时,不可重复执行
if( sRunState.equals(Constants.TASK_STATUS_ENUM.FINISHED.getCode() )){
log.info("日期:["+date+"],工作流编号:["+sTaskflowno+"]的状态是已执行状态,不可重复执行!");
XxlJobLogger.log("日期:["+date+"],工作流编号:["+sTaskflowno+"]的状态是已执行状态,不可重复执行!");
return false;
}
//2.将此任务流下的“错误”状态的任务,更新为“可执行”状态
//where条件
Example example = new Example(TdWorktasktrc.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("dTaskdate",date);
criteria.andEqualTo("sTaskflowno",sTaskflowno);
criteria.andEqualTo("sRunstate",Constants.TASK_STATUS_ENUM.FAILED.getCode());
TdWorktasktrc recode = new TdWorktasktrc();
recode.setsRunstate(Constants.TASK_STATUS_ENUM.EXECUTABLE.getCode());
int num = tdWorktasktrcMapper.updateByExampleSelective(recode,example);
if(log.isDebugEnabled()){
log.debug("根据日期:["+date+"],工作流编号:["+sTaskflowno+"],有"+num+"条失败任务被更新为可执行状态任务!");
}
} catch (Exception e) {
log.error("调用任务流准备工作出现异常", e);
}
return true;
}
/**
* @Description:执行任务完成后续操作
* @Param: [workDate, taskFlowNo, taskNo]
* @Teturn: void
* @Date: Created in 2019/1/8 9:53
*/
public void doTaskFinishFollowOp(Date workDate, String taskFlowNo, String taskNo) {
try {
int updatecount = 0;
TdWorktasktrc record;
TdWorktaskflowtrc taskFlowRecord;
//(1)更新当前任务状态
//where条件
Example example = new Example(TdWorktasktrc.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("dTaskdate",workDate);
criteria.andEqualTo("sTaskflowno",taskFlowNo);
criteria.andEqualTo("sTaskno",taskNo);
record = new TdWorktasktrc();
record.setsRunstate(Constants.TASK_STATUS_ENUM.FINISHED.getCode());
record.setsIsfinished(Constants.TASK_FINISHED_STATE);
record.setsErrdesc("");
updatecount = tdWorktasktrcMapper.updateByExampleSelective(record,example);
if(log.isDebugEnabled()){
log.debug("根据日期:["+workDate+"],任务流编号:["+taskFlowNo+"],任务编号:["+taskNo+"],有"+updatecount+"条任务被更新为执行成功状态!");
}
//(3)更新任务流已完成子任务数量
Map param = new HashMap();
param.put("taskdate",workDate);
param.put("taskflowno",taskFlowNo);
batchProcessGeneralMapper.updateTaskFlowFinishNumber(param);
//(4)更新根任务后置任务
TdWorktaskflowtrc t = new TdWorktaskflowtrc();
t.setdTaskdate(workDate);
t.setsTaskflowno(taskFlowNo);
TdWorktaskflowtrc s = tdWorktaskflowtrcMapper.selectOne(t);
int finishNum = s.getiFinishsubtasknum();
int subNum = s.getiSubtasknum();
if(finishNum == subNum){
//(4.1)更新任务流状态为已完成
//where条件
Example taskFlowExample = new Example(TdWorktaskflowtrc.class);
Example.Criteria taskFlowCriteria = taskFlowExample.createCriteria();
taskFlowCriteria.andEqualTo("dTaskdate",workDate);
taskFlowCriteria.andEqualTo("sTaskflowno",taskFlowNo);
taskFlowRecord = new TdWorktaskflowtrc();
taskFlowRecord.setsIsfinished(Constants.TASK_FINISHED_STATE);
taskFlowRecord.setsRunstate(Constants.TASK_STATUS_ENUM.FINISHED.getCode());
tdWorktaskflowtrcMapper.updateByExampleSelective(taskFlowRecord,taskFlowExample);
//(4.2)更新后置任务流中的根任务状态为可执行状态
//查找后置任务流编号
TdWorktaskflowtrc postObjCond = new TdWorktaskflowtrc();
postObjCond.setsFronttaskflowno(taskFlowNo);
postObjCond.setdTaskdate(workDate);
TdWorktaskflowtrc laterResult = tdWorktaskflowtrcMapper.selectOne(postObjCond);
if(laterResult!=null){
//后置任务流编号
String laterTaskFlowNo = laterResult.getsTaskflowno();
if(StringUtils.isNotBlank(laterTaskFlowNo)){
//where条件
Example e = new Example(TdWorktasktrc.class);
Example.Criteria c = e.createCriteria();
c.andEqualTo("dTaskdate",workDate);
c.andEqualTo("sTaskflowno",laterTaskFlowNo);
record = new TdWorktasktrc();
record.setsRunstate(Constants.TASK_STATUS_ENUM.EXECUTABLE.getCode());
tdWorktasktrcMapper.updateByExampleSelective(record,e);
}
}
//创建发布事件并发布
TaskEvent<TdWorktaskflowtrc> taskEvent = TaskEvent.newInstance(t);
TaskEventPublisher.publishEventAsync(taskEvent);
}
} catch (Exception e) {
log.error("根据日期:["+workDate+"],任务流编号:["+taskFlowNo+"],任务编号:["+taskNo+"],执行任务完成后续操作异常", e);
}
}
public void doTaskFailFollowOp(Date workDate,String taskFlowNo,String taskNo,String sErrdesc){
try{
if(log.isDebugEnabled()){
log.info("任务日期:["+ DateUtils.formatDate(workDate,"yyyyMMdd")+"],任务流编号:["+taskFlowNo+"],任务编号:["+taskNo+"]出现异常!");
}
Example example = new Example(TdWorktasktrc.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("sTaskno",taskNo);
criteria.andEqualTo("dTaskdate",workDate);
criteria.andEqualTo("sTaskflowno",taskFlowNo);
//限制错误最大字符数量
if(sErrdesc!=null) {
if (sErrdesc.length() > Constants.MAX_LENGTH_OF_ERROR_INFO) {
sErrdesc = sErrdesc.subSequence(0, Constants.MAX_LENGTH_OF_ERROR_INFO).toString();
}
}
TdWorktasktrc record = new TdWorktasktrc();
record.setsErrdesc(sErrdesc);
record.setsRunstate(Constants.TASK_STATUS_ENUM.FAILED.getCode());
tdWorktasktrcMapper.updateByExampleSelective(record,example);
} catch (Exception e) {
log.error("根据日期:["+workDate+"],任务流编号:["+taskFlowNo+"],任务编号:["+taskNo+"],任务执行失败后续操作异常", e);
}
}
/**
* 通过工作日期和任务流编号,修改任务流和任务状态为已执行状态
* @param date
* @param taskFlowNo
* @throws Exception
*/
public void updateTaskStateByRunned(Date date,String taskFlowNo) throws Exception{
try{
//(1)更新任务编号为已执行状态
//where条件
Example example = new Example(TdWorktasktrc.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("dTaskdate",date);
criteria.andEqualTo("sTaskflowno",taskFlowNo);
TdWorktasktrc record = new TdWorktasktrc();
record.setsRunstate(Constants.TASK_STATUS_ENUM.FINISHED.getCode());
record.setsIsfinished(Constants.TASK_FINISHED_STATE);
record.setsErrdesc("");
tdWorktasktrcMapper.updateByExampleSelective(record,example);
//(2)更新任务流为已执行状态
//where条件
Example taskFlowExample = new Example(TdWorktaskflowtrc.class);
Example.Criteria taskFlowCriteria = taskFlowExample.createCriteria();
taskFlowCriteria.andEqualTo("dTaskdate",date);
taskFlowCriteria.andEqualTo("sTaskflowno",taskFlowNo);
TdWorktaskflowtrc taskFlowRecord = new TdWorktaskflowtrc();
taskFlowRecord.setsIsfinished(Constants.TASK_FINISHED_STATE);
taskFlowRecord.setsRunstate(Constants.TASK_STATUS_ENUM.FINISHED.getCode());
tdWorktaskflowtrcMapper.updateByExampleSelective(taskFlowRecord,taskFlowExample);
//(4.1)更新任务流状态为已完成
//where条件
taskFlowExample = new Example(TdWorktaskflowtrc.class);
taskFlowCriteria = taskFlowExample.createCriteria();
taskFlowCriteria.andEqualTo("dTaskdate",date);
taskFlowCriteria.andEqualTo("sTaskflowno",taskFlowNo);
taskFlowRecord = new TdWorktaskflowtrc();
taskFlowRecord.setsIsfinished(Constants.TASK_FINISHED_STATE);
taskFlowRecord.setsRunstate(Constants.TASK_STATUS_ENUM.FINISHED.getCode());
tdWorktaskflowtrcMapper.updateByExampleSelective(taskFlowRecord,taskFlowExample);
//(4.2)更新后置任务流中的根任务状态为可执行状态
Map p = new HashMap();
p.put("taskdate",date);
p.put("fronttaskflowno",taskFlowNo);
tdWorktasktrcMapper.updatePostTaskState(p);
//(4.3)更新任务流中的所有任务状态为可执行状态
//where条件
Example taskExample = new Example(TdWorktasktrc.class);
Example.Criteria taskCriteria = taskExample.createCriteria();
taskCriteria.andEqualTo("dTaskdate",date);
taskCriteria.andEqualTo("sTaskflowno",taskFlowNo);
TdWorktasktrc taskRecord = new TdWorktasktrc();
taskRecord.setsIsfinished(Constants.TASK_FINISHED_STATE);
taskRecord.setsRunstate(Constants.TASK_STATUS_ENUM.FINISHED.getCode());
tdWorktasktrcMapper.updateByExampleSelective(taskRecord,taskExample);
} catch (Exception e){
log.error("通过任务流编号:"+taskFlowNo+"修改任务流和任务的状态为已执行状态出现异常", e);
}
}
/**
* 在规定时间内轮旬判断任务流状态,直到为完成状态,如超出规定时间,则抛出RunTimeException
* @param taskFlowNo
*/
public boolean judgePreTaskFlow(Date taskDate,String taskFlowNo,long waitTime) throws Exception{
long start = DateUtils.getSysDate().getTime();
String taskFlowCmt =findTaskFlowNoCmt(taskDate,taskFlowNo);
long end = 0;
boolean keepRunning = true;
while(keepRunning){
TdWorktaskflowtrc tdWorktaskflowtrc = new TdWorktaskflowtrc();
tdWorktaskflowtrc.setdTaskdate(taskDate);
tdWorktaskflowtrc.setsTaskflowno(taskFlowNo);
TdWorktaskflowtrc tdWorktaskflowtrcResultDto = tdWorktaskflowtrcMapper.selectOneNonUseCache(tdWorktaskflowtrc);
String sRunstate = tdWorktaskflowtrcResultDto.getsRunstate();
if(sRunstate.equals(Constants.TASK_STATUS_ENUM.FINISHED.getCode())){
log.info("[前置任务流编号:"+taskFlowNo+",前置任务流名称:"+taskFlowCmt+"]前置任务流已执行成功");
XxlJobLogger.log("[前置任务流编号:"+taskFlowNo+",前置任务流名称:"+taskFlowCmt+"]前置任务流已执行成功");
return true;
}else{
TdWorktasktrc tdWorktasktrc = new TdWorktasktrc();
tdWorktasktrc.setdTaskdate(taskDate);
tdWorktasktrc.setsTaskflowno(taskFlowNo);
int num = tdWorktasktrcMapper.getErrorTaskNum(taskDate,taskFlowNo);
if(num!=0){
log.info("[前置任务流编号:"+taskFlowNo+",前置任务流名称:"+taskFlowCmt+"]前置任务流已存在错误任务,不在等待");
XxlJobLogger.log("[前置任务流编号:"+taskFlowNo+",前置任务流名称:"+taskFlowCmt+"]前置任务流已存在错误任务,不在等待");
return false;
}else{
log.info("正在等待[前置任务流编号:"+taskFlowNo+",前置任务流名称:"+taskFlowCmt+"]前置任务流完成");
XxlJobLogger.log("正在等待[前置任务流编号:"+taskFlowNo+",前置任务流名称:"+taskFlowCmt+"]前置任务流完成");
end = DateUtils.getSysDate().getTime();
long diff = (end-start)/1000;
if(waitTime < diff){
log.info("[前置任务流编号:"+taskFlowNo+",前置任务流名称:"+taskFlowCmt+"]"+"前置任务流超时,后续任务流不在执行");
XxlJobLogger.log("[前置任务流编号:"+taskFlowNo+",前置任务流名称:"+taskFlowCmt+"]"+"前置任务流超时,后续任务流不在执行");
return false;
}
}
}
Thread.sleep(15000);
}
return true;
}
public String findTaskFlowNoCmt(Date taskDate,String taskFlowNo) throws Exception{
TdWorktaskflowtrc dto = new TdWorktaskflowtrc();
dto.setdTaskdate(taskDate);
dto.setsTaskflowno(taskFlowNo);
TdWorktaskflowtrc tdWorktaskflowtrc = tdWorktaskflowtrcMapper.selectOneNonUseCache(dto);
String taskFlowCmt = "";
if(tdWorktaskflowtrc!=null){
taskFlowCmt = tdWorktaskflowtrc.getsTaskflowcmt();
}
return taskFlowCmt;
}
/**
* @Description:根据工作日期、任务流编号获取前置任务流编号
* @Param: [taskDate, taskFlowNo]
* @Teturn: java.lang.String
* @Date: Created in 2019/3/21 14:31
*/
public String findFrontTaskFlowNo(Date taskDate,String taskFlowNo) throws Exception{
String frontTaskFlowNo = null;
TdWorktaskflowtrc dto = new TdWorktaskflowtrc();
dto.setdTaskdate(taskDate);
dto.setsTaskflowno(taskFlowNo);
TdWorktaskflowtrc tdWorktaskflowtrc = tdWorktaskflowtrcMapper.selectOneNonUseCache(dto);
if(tdWorktaskflowtrc!=null){
frontTaskFlowNo = tdWorktaskflowtrc.getsFronttaskflowno();
}
return frontTaskFlowNo;
}
任务IJobHandler 代码示例
package com.xxl.job.executor.jobhandler.batchpdf.handler;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHandler;
import com.xxl.job.core.log.XxlJobLogger;
import com.xxl.job.executor.base.ExecuteTaskConfig;
import com.xxl.job.executor.jobhandler.batchpdf.service.BatchPdfService;
import com.xxl.job.executor.jobhandler.common.persistence.service.BatchProcessGeneralService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.util.Date;
/**
* @Author:shaowei
* @Description:批量生成pdf[任务流编号:117]
* @Date:Created in 2019/1/3 11:02
* @Modified By:
*/
@JobHandler(value="batchpdf")
@Component
public class BatchPdfHandler extends IJobHandler {
@Autowired
private BatchProcessGeneralService batchProcessGeneralService;
@Autowired
private ExecuteTaskConfig executeTaskConfig;
@Autowired
private BatchPdfService batchPdfService;
final String CURRENT_TASK_FLOW_NO = "117";
@Override
public ReturnT<String> execute(String param) throws Exception {
Date date = batchProcessGeneralService.queryCurrentDateWork();
String frontTaskFlowNo = batchProcessGeneralService.findFrontTaskFlowNo(date, CURRENT_TASK_FLOW_NO);
long waitTime = executeTaskConfig.getTaskFlowNoWaitTime108();
Boolean flag = batchProcessGeneralService.judgePreTaskFlow(date, frontTaskFlowNo, waitTime);
if (flag) {
if (batchProcessGeneralService.doPrepareForTaskFlow(date, CURRENT_TASK_FLOW_NO)) {
batchPdfService.batchPdfHandle(date, CURRENT_TASK_FLOW_NO);
XxlJobLogger.log("批量生成pdf :success");
return ReturnT.SUCCESS;
} else {
return ReturnT.FAIL;
}
} else {
return ReturnT.FAIL;
}
}
}
任务核心线程代码样例
package com.xxl.job.executor.jobhandler.batchpdf.thread;
import com.jcraft.jsch.ChannelSftp;
import com.xxl.job.config.spring.SpringContextHolder;
import com.xxl.job.executor.base.constant.Constants;
import com.xxl.job.executor.jobhandler.batchpdf.chain.IPDFGenerator;
import com.xxl.job.executor.jobhandler.batchpdf.chain.PDF;
import com.xxl.job.executor.jobhandler.batchpdf.chain.PDFGenerateChain;
import com.xxl.job.executor.jobhandler.batchpdf.chain.PDFGeneratorContainer;
import com.xxl.job.executor.jobhandler.batchpdf.service.BatchPdfService;
import com.xxl.job.executor.jobhandler.batchpdf.service.InWarehouseFlowService;
import com.xxl.job.executor.jobhandler.common.persistence.dto.TdBpbase;
import com.xxl.job.executor.jobhandler.common.persistence.dto.TdWorktasktrc;
import com.xxl.job.executor.jobhandler.common.persistence.mapper.TdBpbaseMapper;
import com.xxl.job.executor.jobhandler.common.persistence.service.BatchProcessGeneralService;
import com.xxl.job.executor.jobhandler.common.persistence.service.CommonService;
import com.xxl.job.executor.jobhandler.common.persistence.service.TdWorktasktrcService;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import tk.mybatis.mapper.entity.Example;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
/**
* @Description:批量报表生成
* @Param:
* @Teturn:
* @Date: Created in 2019/7/10 10:36
*/
public class BatchPdfThread extends Thread {
private static Log log = LogFactory.getLog(BatchPdfThread.class);
private Date taskDate;
private String taskFlowNo;
private Map<String, TdBpbase> baseMap;
private LinkedBlockingQueue<TdWorktasktrc> taskQueue;
private boolean keepRunning = true;
/**
* 用countDownLatch 来判断任务是否执行完成,执行成功,countDownLatch - 1
*/
private CountDownLatch countDownLatch;
public BatchPdfThread(Date taskDate, String taskFlowNo, LinkedBlockingQueue<TdWorktasktrc> taskQueue, Map<String, TdBpbase> baseMap, CountDownLatch countDownLatch) {
this.taskDate = taskDate;
this.taskFlowNo = taskFlowNo;
this.taskQueue = taskQueue;
this.baseMap = baseMap;
this.countDownLatch = countDownLatch;
}
public BatchPdfThread() {
super();
}
@Override
public void run() {
log.info(Thread.currentThread().getName() + "线程启动");
BatchProcessGeneralService batchProcessGeneralService = SpringContextHolder.getBean(BatchProcessGeneralService.class);
BatchPdfService batchPdfService = SpringContextHolder.getBean(BatchPdfService.class);
PDFGenerateChain pdfGenerateChain = new PDFGenerateChain();
while (keepRunning) {
TdWorktasktrc taskObject = null;
String taskNo = null;
try {
taskObject = taskQueue.poll();
if (taskObject != null) {
taskNo = taskObject.getsTaskno();
PDF pdf = new PDF(taskDate, taskNo);
pdfGenerateChain.generatePDF(pdf);
//处理任务-结束
doTaskFinishFollowOp(taskDate, taskFlowNo, taskNo);
countDownLatch.countDown();
} else {
keepRunning = false;
}
} catch (Exception e) {
log.error("线程[" + Thread.currentThread().getName() + "]执行批量报表生成异常", e);
batchProcessGeneralService.doTaskFailFollowOp(taskDate, taskFlowNo, taskNo, e.getMessage());
}
}
log.info("无可执行任务," + Thread.currentThread().getName() + "线程结束");
}
public synchronized void doTaskFinishFollowOp(Date date, String taskFlowNo, String taskNo) throws Exception {
try {
BatchProcessGeneralService batchProcessGeneralService = SpringContextHolder.getBean(BatchProcessGeneralService.class);
batchProcessGeneralService.doTaskFinishFollowOp(date, taskFlowNo, taskNo);
} catch (Exception e) {
log.error("执行任务完成后续操作异常", e);
throw e;
}
}
public void doTaskFailFollowOp(Date date, String taskFlowNo, String taskNo, String errorInfo) throws Exception {
try {
BatchProcessGeneralService batchProcessGeneralService = SpringContextHolder.getBean(BatchProcessGeneralService.class);
batchProcessGeneralService.doTaskFailFollowOp(date, taskFlowNo, taskNo, errorInfo);
} catch (Exception e) {
log.error("执行任务失败后续操作异常", e);
}
}
}