0 开发阶段 -- 技术选型问答

技术选型:
https://blog.csdn.net/ZuanShi1111/article/details/153681606
https://documentation.flowable.com/latest/reactmodel/bpmn/reference/service-task

根据etc/drsp_mod的 drspDeploy.bpmn20.xml ,尝试写一个通用的flowable任务系列,解析和完善其中的函数,每个函数都打印自己的函数名。
1. 修改pom文件
2. 分析现有代码结构
3. 在service目录下创建drsp目录实现主要逻辑
3. 写UT进行测试​​ 
上述flowable代码请补充集成测试,完整执行流程,请重新执行任务,确保生成的代码可靠运行
集成测试UT AI修复经验:

根本原因:NoClassDefFoundError: SpringProcessEngineConfiguration — Spring Boot 测试基础设施干扰了 @SpringJUnitConfig,导致上下文加载失败。
正确方案:放弃 Spring 上下文配置,直接用 Flowable standalone 引擎 + setBeans() 注册 delegate,这是 Flowable 官方推荐的测试方式,完全不依赖 Spring Boot 自动配置:

基于已有需求设计文档(doc/drsp/drsp1.0.5.md)、业务流程图(etc/drsp)和 Flowable 基础配置,设计任务体系。

仅实现以下四个功能,不引入额外复杂任务类型:
1. 任务下发:流程到达用户任务时,通过 candidateUsers 或 candidateGroups 动态指定办理人;调用 TaskService.complete() 完成当前任务并自动创建下一任务。
2. 进度查询:使用 HistoryService 查询 ACT_HI_TASKINST 表,按流程实例 ID 获取已完成和当前任务列表,计算完成比例(已完成任务数/总任务数)。
3. 超时处理:为用户任务添加边界时间事件(<boundaryEvent><timerEventDefinition>),设置 dueDate 或持续时间。超时后自动触发一个服务任务(serviceTask)发送通知或更新业务状态。
4. 任务重试:为服务任务或外部系统调用配置 async="true" 并设置 failedJobRetryTimeCycle(如 R3/PT5M),失败时自动重试3次,间隔5分钟;用户任务不支持自动重试,改为设计“重新提交”按钮调用 TaskService.setAssignee 重新指派。

基于已有需求设计文档(doc/drsp/drsp1.0.5.md)、业务流程图(etc/drsp)和 Flowable 基础配置,设计任务持久化体系设计。
1. drsp本身是否存数据库?
2. 结合总需求文档, 任务体系还需要存储哪些数据到数据库?
 -- 结论:大部分重叠,回到穿刺部分,完成任务结果查询、进度查询、重试、超时重试。
1. 对现有代码进行补充,满足开发规范 javaAgent.md
2. 提供接口,完成任务下发、结果查询、进度查询、重试、超时重试。
## `delegateExpression` vs `expression` 的区别

### 核心区别

| 特性 | `delegateExpression` | `expression` |
|------|---------------------|--------------|
| 目标 | Spring Bean,实现 `JavaDelegate` | 任意 Spring Bean 的方法调用 |
| 写法 | `${deployDrsp}` → Bean 本身 | `${deployDrspService.deploy(execution)}` → 方法调用 |
| 执行方式 | Flowable 调用 `execute(DelegateExecution)` | Flowable 直接调用指定方法,拿到返回值即完成 |
| 事务边界 | Flowable 管理,支持 async 持久化 | 同上,但行为有差异(见下) |

### 为什么 `delegateExpression` + `async=true` 显示 RUNNING,而 `expression` 直接 COMPLETED

**根本原因:`flowable:async="true"` 的工作机制。**

1. **`async=true`** 的作用是:当流程流转到该任务时,Flowable **先提交事务**(将任务状态持久化到数据库),再由异步 Job Executor 在**新线程/新事务**中执行任务。

2. **`delegateExpression`** 场景:
   - Flowable 将 `deployDrsp` 任务标记为异步作业,**先落库**(状态为 `WAITING/JOB`),此时查进程状态是 `RUNNING`
   - Job Executor 取出作业,新事务中调用 `DeployDrspDelegate.execute()`,里面 `sleep(120s)` → 期间进程一直是 `RUNNING`
   - 完成后流程才推进

3. **`expression`** 场景(例如 `${deployDrspService.deploy(execution)}`):
   - Flowable 同样会尝试异步,但 **`expression` 直接在 EL 求值时执行方法**
   - 如果方法体内部没有阻塞(或者 Flowable 的 async job executor 未正确配置),EL 求值完成即代表任务完成
   - 更关键的是:**`expression` 方法的返回值被视为任务的输出**,Flowable 认为方法调用结束就是任务结束,直接推进到下一个节点 → 最终整个流程快速到达 `end` → 状态变为 `COMPLETED`

---

### 深层原因:异步边界的差异

delegateExpression + async=true:
  主线程: start → prepareDrsp → [提交事务,deployDrsp进入JOB队列] 
  返回: 进程状态=RUNNING ✓
  异步线程: 取出JOB → 执行 execute() → sleep(120s) → 完成 → 继续后续流程

expression + async=true:
  主线程: start → prepareDrsp → [标记async] → Job Executor取出 
  → EL求值: deployDrspService.deploy() 直接执行并返回
  → Flowable认为完成 → 继续后续节点 → end
  → 进程状态=COMPLETED ✗(sleep可能未生效或在后台游离)

**本质**:`JavaDelegate.execute()` 是 Flowable 的**生命周期回调**,Flowable 等它执行完才认为任务结束;而 `expression` 的方法调用是 **EL 求值**,求值返回即结束,Flowable 不感知方法内部的异步行为。


你的场景(需要执行耗时操作、需要进程处于 RUNNING 状态)**必须用 `delegateExpression`**,配合 `flowable:async="true"`,才能保证:
- 耗时操作在异步线程中真正执行
- 期间查询流程实例状态为 `RUNNING`
- 操作完成后流程才推进

决策

  1. 考虑长期软件需要升级考虑 -- 问:目前的superInsight 像是工具一样纳管。后续如果上了license需求,SI升级的工作是不是也要考虑【目前没有升级】,不知道license能不能像insight 信息excel一样自由的导入导出。答:不能这么导入导出了。因为要引入SI 与Insight之间的心跳机制,你吧license卸载了,会引发Insight的license也卸载。
  2. flowable软件会自动生成sql语句
  3. 开源软件会不断迭代,flowable的sql升级成为隐患

项目初期使用flowable快速验证,后续单独实现task简化版。保证核心task可替换。

posted @ 2026-04-18 10:32  静水深耕,云停风驻  阅读(20)  评论(0)    收藏  举报