feat:取消完成通过配置决定是否使用mq或者feign

This commit is contained in:
2026-08-03 19:30:54 +08:00
parent 1e3f95eace
commit d9f21147aa
26 changed files with 841 additions and 88 deletions

View File

@@ -0,0 +1,72 @@
# 任务完成与取消双通道回调设计
## 目标
任务模块根据 YAML 配置选择 MQ 异步或 Feign 同步方式通知 LMS/WMS 执行完成、取消业务;业务处理成功后,两条链路都由 Task 服务统一把任务从回调待处理状态推进到最终完成或取消状态。
## 当前问题
- `TransportTaskOperationManager#handleFinished``handleCancelled` 固定发布 RocketMQ 消息,无法切换为同步 Feign。
- LMS/WMS 的 MQ Consumer 调用 `AbstractTask#doHandleFinish``doHandleCancel` 后没有回调 Task任务停留在 `FINISHED_CALLBACK_PENDING``CANCEL_CALLBACK_PENDING`
- `TransportTaskCallbackServiceImpl` 使用 `%03d` 格式化字符串状态码,回调处理存在运行时类型异常。
- `TaskCommonApi` 只暴露取货、进出等动作,没有完成和取消接口。
## 配置
在 Task 服务 YAML 中增加必填配置:
```yaml
nl:
task:
callback-type: mq
```
允许值为 `mq``feign`。使用枚举解析配置;配置缺失或值非法时启动失败,不做静默兜底。默认项目配置使用 `mq`,保持现有部署行为。
## 执行链路
### MQ 异步模式
1. Task 将任务置为对应的回调待处理状态,并把 `callbackStatus` 置为 `PENDING`
2. 当前事务提交后发布完成或取消消息。
3. LMS/WMS Consumer 校验任务仍处于当前事件对应的待处理状态,然后路由到 `AbstractTask` 子类执行业务。
4. 业务成功后Consumer 写入带有效期的 Redis 成功标识,再通过 `TransportTaskApi.receiveCallbackResult` 回调 `SUCCESS`若成功回调失败MQ 重试时只重试回调,不重复执行业务。
5. Task 的统一回调服务把任务更新为 `FINISHED``CANCELLED`,并把 `callbackStatus` 置为 `SUCCESS`
6. 业务异常时Consumer 尝试回调 `FAILED` 记录错误与重试次数,再重新抛出异常,让 MQ 执行重试。
### Feign 同步模式
1. Task 将任务置为对应的回调待处理状态,并把 `callbackStatus` 置为 `PENDING`
2. Task 根据 `ownerService``TaskCommonApiFactory` 获取 LMS/WMS Feign Client。
3. 调用新增的 `doHandleFinished``doHandleCancelled`,业务服务通过 `TaskFactory` 路由到相同的 `AbstractTask` 子类。
4. Feign 返回成功后Task 直接调用统一回调服务,以相同规则更新最终状态。
5. Feign 返回失败或抛出异常时不进入最终状态,异常沿现有任务操作链路上抛。
## 接口与数据
-`TaskCommonApi` 增加 `doHandleFinished``doHandleCancelled`
- 两个接口继续复用 `TaskStatusCallApiReqDTO`,携带任务标识、业务归属、业务标识、处理器编码和 payload。
- 同步与异步链路都复用 `TaskCallbackResultReqDTO``TransportTaskCallbackService` 完成最终状态收口。
- `eventId` 使用任务 ID 与事件类型组成的稳定值Task 按当前 pending 状态校验 eventId拒绝延迟或错序事件推进错误终态。
## 幂等与错误处理
- Task 已处于 `FINISHED``CANCELLED` 时忽略重复成功回调。
- 只有 `FINISHED_CALLBACK_PENDING` 能推进到 `FINISHED`,只有 `CANCEL_CALLBACK_PENDING` 能推进到 `CANCELLED`
- MQ 重复消息在消费前查询 Task 状态;状态已不匹配时直接跳过。
- MQ 业务成功后使用七天 Redis 标识隔离业务执行与 Task 成功回调重试;成功回调完成后删除标识。
- Feign `CommonResult` 必须调用 `getCheckedData` 或检查 `isSuccess`,业务失败不允许误更新最终状态。
- MQ 回调失败不吞掉业务异常,保留 RocketMQ 重试能力。
- 任务状态分布式锁延迟到本地事务完成后释放,避免提交前窗口发生并发重复处理。
## 验证
- Spring 集成测试验证 execute starter 的完成、取消 Feign 入口能正确路由到任务处理器。
- 编译 execute starter、task-api、task-server、lms-server、wms-server验证跨模块接口一致。
- 检查 MQ 成功回调和 Feign 成功返回最终都进入统一状态处理服务。
## 一致性边界
- MQ 和 Feign 均向 `AbstractTask` 透传稳定的 `eventId``eventType`,业务处理器应以该事件标识在业务数据库中实现幂等。
- Redis 成功标识可以避免“业务已成功、Task 成功回调失败”时重复执行业务但不能覆盖业务事务提交后、Redis 标识写入前进程崩溃的极小窗口,因此业务数据库幂等仍是最终保障。
- Feign 调用与 Task 本地事务不构成分布式事务;远端成功后若本地事务回滚,重试仍依赖上述事件幂等。