Activiti7 工作流非原流程终止
背景
正常工作流,需要经过 node1、node2 才能结束。
现在要求已经开启的流程,目前停留在 node1,可以提前终止。
方案
一般根据实际需要,可以有几种做法:
- 新绘制流程图,新增 node1 结束的流程分支,替换原流程
- SQL 的方式,将该流程的数据,手动修改为终止的状态
- 代码动态修改流程模型,并使其流转只流向终止状态
下面分析一下这些方式的应用场景及优缺点。
新绘制流程图
新流程图
替换原流程图
UPDATE ACT_GE_BYTEARRAY SET BYTES_ = '新流程的对应值' WHERE _ID = xxx AND NAME_ = 'xxxxx.bpmn';
## 以下根据情况可选,在使用 activiti5 时有碰到
UPDATE ACT_GE_BYTEARRAY SET BYTES_ = '新流程的对应值' WHERE _ID = xxx AND NAME_ = 'xxx.png';
UPDATE ACT_GE_BYTEARRAY SET BYTES_ = '新流程的对应值' WHERE _ID = xxx AND NAME_ = 'source';
UPDATE ACT_GE_BYTEARRAY SET BYTES_ = '新流程的对应值' WHERE _ID = xxx AND NAME_ = 'source-extra';
后续根据条件,正确提交即可,可以正常流转。
优缺点
- 优点
- 新的流程分支可以从流程图上体现,一目了然;
- 符合工作流的生命周期,正常应用工作流的监听器
- 全局应用
- 缺点
- 修改工作流比较麻烦
- 如果改动比较多,而且部分流程已经过了 node1 的话,可能会导致实时绘制流程报错。
- 需要注意新老代码层面的兼容性(前提数据库唯一,但代码蓝绿发布)
应用场景
改动是全局的;
工作流模型改动有良好的版本管理和上线流程;
流程图需要体现这个分支流程(是正常业务应该关心的流转)
SQL修改工作流数据
DELETE FROM act_ru_task WHERE ID_ = 'xxxx';
DELETE FROM act_ru_variable WHERE PROC_INST_ID_ = 'xxxx';
DELETE FROM act_ru_execution WHERE ID_ = 'xxxx';
UPDATE act_hi_taskinst SET END_TIME_ = '2023-02-20 21:57:47.033000', DURATION_= 4180506 WHERE ID_ = 'xxxx';
UPDATE act_hi_procinstSET END_TIME_ = '2023-02-20 21:57:47.033000', DURATION_= 4180506, END_ACT_ID_ = 'endevent_oc' WHERE PROC_INST_ID_ = 'xxxx';
优缺点
- 优点
- 一次性,不用开发临时性代码
- 缺点
- SQL 改动风险高
- 无法使用工作流层面的监听器
- 如果存在业务数据修复,需要同时处理
应用场景
一次性流程关闭,无业务数据修复
代码动态修改流程模型
/**
* 提前终止业务流程实例,适用场景:当前任务节点没有对应的流程结束节点(业务变更导致需要终止流程)
*/
public void terminateProcessByBusinessKey(String businessKey) {
taskService.createTaskQuery()
.processInstanceBusinessKey(businessKey)
.list()
.forEach(task -> terminateProcessByTask(task.getId(), task));
}
private void terminateProcessByTask(String taskId, Task task) {
if (Objects.isNull(task)) {
log.warn("流程任务实例不存在. taskId: {}", taskId);
return;
}
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
EndEvent endEvent = bpmnModel.getMainProcess().findFlowElementsOfType(EndEvent.class).get(0);
FlowNode currentNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(task.getTaskDefinitionKey());
List<SequenceFlow> orignOutgoingFlows = currentNode.getOutgoingFlows();
SequenceFlow endFlow = new SequenceFlow();
endFlow.setId("flow_to_temp_end");
endFlow.setSourceFlowElement(currentNode);
endFlow.setTargetFlowElement(endEvent);
// 将当前节点的出向分支替换为流向 flow_to_temp_end
currentNode.setOutgoingFlows(Lists.newArrayList(endFlow));
taskService.complete(taskId);
// 流转完恢复
currentNode.setOutgoingFlows(orignOutgoingFlows);
log.info("非正常方式完成流程. taskId: {},procDefKey: {},caseNo:{}", taskId, bpmnModel.getMainProcess().getId(), task.getBusinessKey());
}
图例:
优缺点
- 优点
- 通用的非正常关闭逻辑,不受限于某个节点
- 可以应用工作流的生命周期,不影响事件触发或监听器
- 可以便于处理业务数据的非正常结束
- 缺点
- 模型的改动是全局的,注意并发
- 无法体现在流程图上
- 实时流程图的生成会有影响
应用场景
- 不仅限于一个节点的流程关闭
- 业务不强要求流程关闭的分支体现在图上
- 短期方案,逐步替换为正常流程
转载自:https://juejin.cn/post/7221434573829488695