Activiti7 工作流非原流程终止

229 阅读3分钟

背景

在这里插入图片描述

正常工作流,需要经过 node1、node2 才能结束。

现在要求已经开启的流程,目前停留在 node1,可以提前终止。

方案

一般根据实际需要,可以有几种做法:

  1. 新绘制流程图,新增 node1 结束的流程分支,替换原流程
  2. SQL 的方式,将该流程的数据,手动修改为终止的状态
  3. 代码动态修改流程模型,并使其流转只流向终止状态

下面分析一下这些方式的应用场景及优缺点。

新绘制流程图

新流程图

在这里插入图片描述

替换原流程图

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());
    }

图例:在这里插入图片描述

优缺点

  • 优点
    • 通用的非正常关闭逻辑,不受限于某个节点
    • 可以应用工作流的生命周期,不影响事件触发或监听器
    • 可以便于处理业务数据的非正常结束
  • 缺点
    • 模型的改动是全局的,注意并发
    • 无法体现在流程图上
    • 实时流程图的生成会有影响

应用场景

  • 不仅限于一个节点的流程关闭
  • 业务不强要求流程关闭的分支体现在图上
  • 短期方案,逐步替换为正常流程