#file:step3-code.md #file:drsp_task.md
1. 整体环境在windows进行,优先进行 step3-code.md 的windows环境检查 【已人工确认,这步跳过】
2. 请结合drsp详设文档 drsp_task.md 、 code编程原则 step3-code.md 、 现有实现的flowable任务基础框架实现,如果理解完仍然有阻塞性的待确认项,请列出退出操作
3. 形成任务清单依次按照任务清单,优先形成文档。
4 逐个完成完成代码撰写 和 UT测试。
根据基于现有flowable的workflow框架,实现自研的bpmn2.0 工作流,先给出详细设计到doc/taskflow.md,任务列表,根据任务列表实现具体的代码。要求如下:
1. flowable太重
2.保证工作流 和 drsp实现独立,保证业务端drsp改动不大
3.实现目录为 src\main\java\com\zte\ws\taskflow
4.保证实现flowable的基础功能
事件(Event):流程起点(Start Event)、终点(End Event)、对中间事件(如定时器、消息事件)不实现,但保持可扩展;
任务(Task):服务任务(Service Task)、对脚本任务(Script Task)不实现,但保持可扩展;
网关(Gateway):排他网关(Exclusive Gateway)、并行网关(Parallel Gateway)、对包容网关(Inclusive Gateway)不实现,但保持可扩展;
5.保证实现任务流的查询功能
6.需要支持 基础的工作流功能、任务持久化、任务进度查询
7.并行网关采用Execution执行流的方式实现
当前项目实现基础的bpmn2.0功能,现在需要支持并发网关。先给出详细设计到doc/taskflow2.md,任务列表,根据任务列表实现具体的代码。要求如下:
1. 参考flowable实现框架
2. 保证并发的安全性
3. 保证变量合并与隔离
4. 对并发任务的任务查询、进度查询设计
5. 对并发任务的重试机制设计
如下动作需要实现beforeExecute -- 获取数据库目标租户的状态work_model,如果work_model是完成后的状态,则跳过handler.buildIaParam(context);
(集群工作模式, 0 - SERVICE,即服务模式;1 - READONLY,即只读模式;2 - SYNC,即同步模式)
动作 -- 完成后的状态
drspSyncToReadOnly -- 1
drspReadonlyToSync -- 2
drspReadonlyToService -- 0
drspSyncToReadonly -- 1
查询sql如下,sql查询实现参考现有代码的写法:
select work_model from mds.cluster_info where cluster_id=<clusterID>;
整体结论
当前 taskflow 已经不是“设计稿对应的代码骨架”,而是 P0 主链路基本落地的最小可用引擎:定义加载、BPMN 解析、执行器注册、异步推进、排他网关、并行 split/join、持久化表、查询、重试、DRSP 适配和基础单测都已经在仓库里。对 taskflow 包做的 IDE 静态检查也没有报错。
工程级评价上,我会把它定义为:架构方向正确、实现并不浅、值得继续投资,但距离“可稳定替代 Flowable 的生产级流程引擎”还差一轮可靠性硬化。作为“单实例、受控 BPMN 子集、DRSP 专用场景”的 v1,可灰度;作为“通用生产工作流内核”,现在还不够稳。
主要问题
阻断 并行失败后的流程快照会被其他分支继续覆盖。一个分支把流程标成 FAILED 在 TaskFlowEngineServiceImpl.java:539 之后,其他已经在跑的分支仍会继续调用 TaskFlowEngineServiceImpl.java:312 和 TaskFlowEngineServiceImpl.java:488 更新 current_node_id、completed_tasks 和变量;而底层更新语句 TaskFlowProcessInstanceMapper.java:70 没有状态或版本保护。这会直接污染失败节点定位和重试起点。
阻断 重试没有隔离旧的 ACTIVE/WAITING execution。当前重试只是新插一条 execution,见 TaskFlowEngineServiceImpl.java:191;流程结束却依赖全实例范围的未完成 execution 计数,见 TaskFlowEngineServiceImpl.java:458 和 TaskFlowExecutionMapper.java:71。并行失败后旧分支残留时,重试后的新 execution 很可能永远收敛不到 COMPLETED。
高 执行推进是进程内异步,join 协调也是进程内锁,不具备崩溃恢复和多实例安全。异步提交发生在 TaskFlowEngineServiceImpl.java:202,并行 join 依赖 TaskFlowEngineServiceImpl.java:70 和 TaskFlowEngineServiceImpl.java:402。这意味着 JVM 重启、线程池任务丢失或多实例部署时,实例可能长期卡在 RUNNING/ACTIVE/WAITING。
高 “同一业务键只允许一个运行流程”不是原子保证。业务侧先在 DrspTaskServiceImpl.java:69 查询,再在 DrspTaskServiceImpl.java:104 启动;引擎侧只是 TaskFlowProcessInstanceMapper.java:43 计数查询,DDL 里 taskflow.sql:16 只有普通索引,没有唯一约束或抢占锁。并发提交下可以双启同一组流程。
中 并行活动的 sequence_no 有竞争条件。当前编号来自 TaskFlowActivityInstanceMapper.java:25 的 max(sequence_no)+1,调用点在 TaskFlowEngineServiceImpl.java:275。一旦并行分支同时落活动记录,顺序号重复或乱序基本不可避免。
中 测试覆盖没有打到最高风险路径。现有测试主要是解析、表达式、异常兜底和 DRSP 映射级别的单测,分别在 TaskFlowBpmnParserTest.java:17、SimpleConditionExpressionEvaluatorTest.java:16、TaskFlowEngineServiceImplTest.java:68、TaskFlowDrspProcessEngineServiceTest.java:46。真正最危险的“真实数据库 + 异步 + 并行失败 + 重试”没有被证明。
中 DRSP 适配层对进度做了二次推导,而不是直接复用引擎进度字段。见 TaskFlowDrspProcessEngineService.java:101。这在并行和重试场景下容易和引擎侧 completedTasks/totalTasks/percentage 出现语义漂移。
低 还有一些收尾痕迹,说明状态契约还没完全打磨完。比如请求 DTO TaskFlowStartRequest.java:8 没有字段校验,而控制器已经挂了 @Valid,见 TaskFlowController.java:36;另外流程启动直接写 RUNNING,见 TaskFlowEngineServiceImpl.java:105,但 PENDING 和 TaskFlowProcessInstanceMapper.java:56 仍然保留。
优点
分层是清楚的,定义加载、解析、执行、注册、适配分别落在 TaskFlowDefinitionRegistry、TaskFlowBpmnParser、TaskFlowEngineServiceImpl、TaskFlowExecutorRegistry、TaskFlowDrspProcessEngineService。这说明方案不需要推翻重做。
内部模型设计比较干净,record 和不可变集合用得克制,像 TaskFlowProcessDefinition 和 TaskFlowProcessDetail 这样的对象边界是稳的。
v1 范围控制是合理的,条件表达式也明确只做最小闭环,见 SimpleConditionExpressionEvaluator。这比继续把完整 Flowable 背进来更务实。
DRSP 接入面压得很小,业务仍然通过 DrspProcessEngineService 走,对现有 service/controller 契约冲击不大。
判断
如果用一句话概括:这套 taskflow 值得继续打磨,不该推翻;但现在更像“可运行的单实例工作流内核”,还不是“已经完成工程硬化的生产级流程引擎”。
自然的下一步只有三件事:
先修状态机一致性:失败后禁止其他分支继续覆盖流程快照,重试时显式终结或隔离旧 execution,并给流程/执行流更新加状态条件或版本控制。
再补运行可靠性:至少要有崩溃恢复或启动扫描机制;如果明确不做,就要把“仅支持单实例、异常后人工恢复”写成部署前提,而不是隐含假设。
最后补真实集成测试:并行 join、并行失败、retry、防重启动、JVM 中断恢复,这几组过了,才谈正式切 Flowable。
最大风险不是网关,而是进程重启后的恢复。执行依赖本地线程池 TaskFlowConfig.java:20,异步提交发生在 TaskFlowEngineServiceImpl.java:204。如果服务在流程运行中重启,实例可能停在 RUNNING,但重试接口只接受 FAILED,见 TaskFlowEngineServiceImpl.java:174。这对当前顺序流程同样是实质风险。
第二个风险是重复提交保护不原子。业务侧先查“是否有运行中流程”,再启动,见 DrspTaskServiceImpl.java:70;底层只是 count 查询,见 TaskFlowProcessInstanceMapper.java:41。表结构里只有普通索引,没有唯一性约束,见 taskflow.sql:16。并发提交同一组任务时,理论上仍可能双启。
第三个问题是验证力度还不够。当前有解析器、表达式、一个引擎异常兜底测试和一个 DRSP 适配测试,见 TaskFlowBpmnParserTest.java、SimpleConditionExpressionEvaluatorTest.java、TaskFlowEngineServiceImplTest.java、TaskFlowDrspProcessEngineServiceTest.java。但还没有看到“真实数据库 + 顺序流程 happy path + 失败重试”的端到端证明。
还有一个较轻的问题是 DRSP 查询结果里的进度是适配层自己重新算的,不是直接复用引擎进度字段,见 TaskFlowDrspProcessEngineService.java:90。这更像显示一致性问题,不是当前主阻断。