工作流(3)——复杂工作流:从驳回、加签到会签

引言

在上一篇中,我们从底层架构拆解了工作流引擎的执行机制(Execution流转)与持久化机制(数据库状态机)。在标准的 BPMN 2.0 规范下,流程是高度结构化且单向向前的。

但在真实的业务场景中,流程绝不仅仅是"同意"和"下一步"。业务人员会提出大量打破常规流转规则的需求。本篇将直接抛弃比喻,纯粹从技术实现与底层 API 出发,直面工作流开发中最棘手的四大问题,并给出破局方案。

1 复杂工作流的破局之道:从驳回、加签到会签

1.1 业务痛点

流程定义为 A(发起) -> B(部门主管) -> C(总监) -> D(财务)

当流程流转到 D 时,财务发现单据有问题,要求直接打回给 B 修改,或者打回给 A 重新发起。

BPMN 2.0 规范中并没有原生的"驳回"连线,如果在画图时将每个节点都连一条线回到起点,会导致流程图极其混乱(面条图),且无法维护。

1.2 技术解析

工作流引擎的核心是维护 Execution(执行实例)在 Activity(节点)之间的位置。向前流转是引擎解析连线(Sequence Flow)自动计算的。要实现向后跳转,我们需要跳过连线解析,直接通过 API 强行修改 Execution 的当前指针位置。

1.3 解决方案(以 Flowable 为例)

现代开源引擎(如 Flowable 6.x)提供了专门的节点跳转 API:ChangeActivityStateBuilder

  1. 获取当前节点与目标节点:通过 API 获取当前正在执行的任务节点 ID,以及需要驳回到的目标节点 ID
  2. 清理当前状态:引擎需要先作废当前节点产生的所有待办任务(Task),并清理当前节点作用域内的局部变量
  3. 指针转移 :通过 API 直接将 Execution 的指针移动到目标节点
  4. 触发执行:引擎在目标节点重新触发进入逻辑,生成新的待办任务

核心代码逻辑:

java 复制代码
// 使用 Flowable 原生 API 实现跳转
runtimeService.createChangeActivityStateBuilder()
    .processInstanceId(processInstanceId)
    .moveActivityIdTo(currentActivityId, targetActivityId) // 从当前节点跳到目标节点
    .changeState();

注意:在执行跳转前,通常需要往历史表中写入一条自定义的批注(Comment),记录"由节点D驳回至节点B,原因:发票不符",以保证审计记录的完整性。

2 问题二:审批人需要临时增加人员,如何实现"动态加签"?

2.1 业务痛点

流程定义中,当前节点是"技术总监审批"。但在实际审批时,技术总监认为这个方案涉及安全问题,需要临时让"安全总监"先审批,或者和"安全总监"一起审批。这个"安全总监"在原流程图中根本不存在。

2.2 技术解析

这涉及两种不同的加签模式,底层处理逻辑完全不同:

  1. 前加签(顺序执行):安全总监先批,批完再还给技术总监
  2. 并签(并行执行):安全总监和技术总监同时审批,两人都同意才算过

2.3 解决方案

2.3.1 场景A:前加签(基于任务委派 Delegation)

引擎原生支持任务的委派。技术总监不直接完成任务,而是调用 taskService.delegateTask(taskId, "安全总监")

此时,底层表 ACT_RU_TASK 中该任务的 ASSIGNEE_(处理人)会变成安全总监,而 OWNER_(所有者)保留为技术总监,任务状态变为 PENDING

安全总监处理完成后,调用 taskService.resolveTask(taskId),任务处理人会自动切回技术总监,流程并没有往下走,完美实现前加签。

2.3.2 场景B:并签(基于多实例动态扩展)

如果要在运行时增加一个并行任务,直接 new Task() 插入数据库是极其危险的,因为独立生成的任务脱离了 Execution 的生命周期管控,完成后无法触发流程继续。

正确的做法是:将该节点在画图时配置为"多实例(Multi-Instance)"节点

当需要动态加签时,通过调用引擎的多实例扩展 API:

java 复制代码
// 动态向多实例节点中追加一个执行实例和任务
runtimeService.addMultiInstanceExecution(
    activityId, 
    processInstanceId, 
    Collections.singletonMap("assignee", "安全总监")
);

引擎会基于当前节点的配置,动态分裂出一个新的 Execution 并生成对应的任务,统一纳入多实例的完成条件计算中。

3 问题三:"5人中3人同意即可",如何实现复杂的"会签/或签"逻辑?

3.1 业务痛点

一个评审节点由 5 名专家组成。业务规则不是"全部同意才通过",而是"只要有 3 人同意即通过";或者"只要有 1 人拒绝,直接一票否决,流程结束"。

3.2 技术解析

在标准节点中,一个任务完成,流程就走向下一步。针对多人审批,必须使用 多实例(Multi-Instance) 节点。

引擎在运行多实例时,会在内部维护三个极其重要的内置变量:

  • nrOfInstances:总实例数(比如 5)
  • nrOfCompletedInstances:已完成的实例数
  • nrOfActiveInstances:当前活动的实例数

3.3 解决方案:基于完成条件(Completion Condition)的表达式注入

在流程定义的 XML 中,为多实例节点配置 <completionCondition> 标签。引擎在每一次单个任务完成时,都会计算这个表达式。如果结果为 true,引擎会立刻销毁剩余未完成的实例,并驱动流程走向下一个节点。

3.3.1 实现"3人同意即通过"

配置表达式:${nrOfCompletedInstances >= 3}

当第 3 个人点击同意并完成任务时,表达式返回 true,剩下的 2 个待办任务会被引擎物理删除,流程进入下一环节。

3.3.2 实现"一票否决"

  1. 任何人在点击"拒绝"时,通过 API 向引擎注入一个局部变量:taskService.setVariableLocal(taskId, "isVeto", true)
  2. 配置完成条件表达式:${isVeto == true || nrOfCompletedInstances == nrOfInstances}
  3. 只要有人触发了否决变量,表达式立即成立,多实例结束。随后在节点后方连接一个排他网关(Exclusive Gateway),根据 isVeto 的值路由到结束节点

4 问题四:发起人点错提交了,如何实现"流程撤回"?

4.1 业务痛点

员工发起请假单,流程已经流转到了部门主管。员工发现天数填错了,想要撤回单据重新修改。

4.2 技术解析

撤回本质上是一种附带条件限制的特定节点跳转 。它与"驳回"的技术实现完全一致(都是通过修改 Execution 指针实现),区别在于业务校验逻辑

4.3 解决方案:严格的校验前置 + 跳转 API

  1. 状态校验 :撤回操作必须在后端进行严格的校验。查询当前流程实例的活动任务列表(taskService.createTaskQuery())。如果目标任务已经被主管签收(Claim)完成(Complete),则抛出业务异常,拒绝撤回
  2. 执行跳转 :如果主管还未处理,调用与"驳回"相同的 ChangeActivityStateBuilder API,将 Execution 从主管节点强制拉回到"开始节点"或专门的"草稿节点"
  3. 数据清理 :撤回后,业务系统需将自身业务表(如 leave_request)的状态从"审批中"更新回"草稿",并允许用户修改表单数据

5 总结

通过对以上四个高频复杂问题的拆解,我们可以得出一个关于工作流引擎的核心结论:

工作流引擎不仅是一套严格遵守 BPMN 规范的解析器,更是一个提供底层状态机操作 API 的基础平台。

面对复杂的业务需求,单纯依靠画图(配置)是无法解决所有问题的。架构师和开发者必须跳出"连线流转"的思维局限,深刻理解 Execution(执行实例)、Task(任务)、Variable(变量)之间的关系,通过代码调用引擎提供的干预 API(如跳转、委派、多实例动态干预),结合业务系统自身的逻辑校验,才能构建出既规范又灵活的企业级工作流中台。

掌握了这些,你就不再只是一个"会用框架调 API 的码农",而是真正具备了掌控复杂流转系统底层逻辑的架构能力。

相关推荐
小花皮猪7 小时前
2026 SERP + LLM 训练数据采集指南(Bright Data MCP + Dify)
人工智能·爬虫·工作流·dify·serp
阿钱真强道9 小时前
18 AnimateDiff 简介:它在 AI 视频生成领域处于什么位置?
animatediff·stable-diffusion·comfyui·工作流·ai视频·新手教程
啾啾Fun1 天前
工作流(2)——工作流引擎的底层架构:从Token到数据库的精密运转
架构·工作流
纪伊路上盛名在3 天前
如何跨设备访问我们VSCode中GitHub Copilot 的聊天记录?
vscode·github·copilot·工作流
程序员洲洲4 天前
OpenClaw + kookeey 动态代理IP:搭建亚马逊电商数据采集与飞书 AI 自动化工作流
飞书·工作流·openclaw·小龙虾·kookeey·飞书ai
liu****6 天前
LangGraph-AI应用开发框架(二)
windows·langchain·大模型·工作流·langgraph
内卷焦虑人士9 天前
LightRAG 接入 Dify
工作流·dify·lightrag
阿钱真强道10 天前
05 ComfyUI + SVD 系列(三):最小图生视频工作流拆解——节点含义、输入输出、参数作用与核心实验
python·aigc·stable-diffusion·svd·comfyui·工作流·图生视频
七夜zippoe11 天前
OpenClaw 多代理协作编排:构建企业级智能协作网络
网络·工作流·openclaw·多代理协作·对等协作