Files
huachuang/doc/task-service-new-architecture-development-design.md

580 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Task 服务新架构详细开发设计方案
## 1. 业务背景与定位
新架构中,系统拆分为通用 `Task` 服务、`LMS` 服务、`WMS` 服务。
其中:
- `LMS`:生产内部搬运业务,例如 AGV 搬运某个架子、托盘、料车到某个生产站点、缓存位、对接位;
- `WMS`仓储出入库业务例如入库、出库、移库、堆垛机搬运、AGV 和立库设备联动;
- `Task`:统一任务服务,负责任务创建记录、任务状态流转、调度下发外部系统、接收外部反馈、任务日志、重试和补偿。
旧架构中 `AbstractAcsTask` 同时承担了任务创建、点位计算、外部下发、完成业务、取消业务等职责。新架构建议将其拆分,避免 Task 服务反向依赖 LMS/WMS 的业务实现。
## 2. 总体设计目标
1. Task 服务成为通用任务中台,只处理任务生命周期和外部系统交互;
2. LMS/WMS 保留各自业务语义和业务数据处理能力;
3. 不再跨服务使用 Java 类名 `handle_class`
4. 使用稳定的 `handler_code` 标识业务处理器;
5. 任务完成、取消时,由 Task 服务通知业务归属服务执行业务回调;
6. 支持 AGV、堆垛机、ACS、WCS 等多种外部系统;
7. 支持同步 RPC 回调,也能平滑演进到 MQ 事件回调;
8. 支持幂等、重试、补偿和人工干预。
## 3. 核心拆分思想
旧版一个 `AbstractAcsTask` 拆成三层能力:
```text
业务任务创建层LMS/WMS
负责业务校验、点位计算、业务参数准备、调用 Task 创建任务
通用任务执行层Task
负责任务状态、任务下发、外部反馈、任务日志、重试补偿
业务结果处理层LMS/WMS
负责完成/取消后的业务确认、库存、单据、点位、分配明细处理
```
对应代码抽象:
```text
LMS/WMSBusinessTaskCreator可选
TaskExternalTaskDispatcher
LMS/WMSTaskBizCallbackHandler
```
## 4. 服务职责边界
### 4.1 LMS 服务职责
LMS 负责生产内部搬运任务的业务语义,例如:
- 判断某个架子是否允许搬运;
- 判断目标站点、缓存位、对接位是否可用;
- 生成生产搬运业务记录;
- 调用 Task 服务创建搬运任务;
- 任务完成后更新生产业务状态;
- 任务取消后回滚生产占用、点位锁定、业务单据状态。
### 4.2 WMS 服务职责
WMS 负责仓储出入库任务的业务语义,例如:
- 入库、出库、移库业务校验;
- 库位分配、库存预占、出入库单据状态维护;
- 调用 Task 服务创建 AGV/堆垛机/输送线任务;
- 任务完成后确认出入库或移库;
- 任务取消后释放库位、回滚库存预占、恢复单据状态。
### 4.3 Task 服务职责
Task 服务只处理通用任务能力:
- 保存任务主表;
- 保存任务明细或任务步骤;
- 管理任务状态机;
- 根据 `external_system` 选择外部系统下发器;
- 下发 AGV/ACS/WCS/堆垛机任务;
- 接收外部系统反馈;
- 根据 `owner_service` 通知 LMS/WMS 做业务回调;
- 记录任务日志;
- 处理重试、超时和补偿。
Task 服务不直接处理 LMS/WMS 的业务表,不直接注入 LMS/WMS 的业务 Service。
## 5. 模块依赖设计
推荐依赖方向:
```text
lms-server -> task-api
wms-server -> task-api
task-server -> task-api
task-server -> lms-api可选仅 RPC 回调需要
task-server -> wms-api可选仅 RPC 回调需要
```
禁止依赖:
```text
task-server -> lms-server
task-server -> wms-server
```
如果采用 MQ 事件方式Task 服务甚至可以不依赖 `lms-api``wms-api`,只发布标准任务事件。
## 6. 新版任务标识设计
旧版:
```text
handle_class = org.nl.b_lms.sch.tasks.TwoInTask
```
新版:
```text
owner_service = LMS
biz_type = PRODUCTION_TRANSFER
handler_code = LMS_RACK_TO_STATION
biz_id = LMS 业务记录 ID
```
或 WMS
```text
owner_service = WMS
biz_type = INBOUND
handler_code = WMS_INBOUND_STACKER
biz_id = WMS 入库单/分配明细 ID
```
字段含义:
| 字段 | 含义 |
| --- | --- |
| `owner_service` | 任务归属业务服务,决定完成/取消回调给谁 |
| `biz_type` | 业务任务类型,用于查询、统计和权限控制 |
| `handler_code` | 业务回调处理器编码,业务服务内部使用 |
| `biz_id` | 业务侧记录 ID用于回查业务数据 |
| `external_system` | 外部执行系统,例如 AGV、ACS、WCS、STACKER |
| `external_task_type` | 外部系统任务类型 |
## 7. 数据模型建议
### 7.1 task_task 主表
| 字段 | 说明 |
| --- | --- |
| `id` | Task 服务任务 ID |
| `task_no` | 任务编号 |
| `owner_service` | LMS/WMS |
| `biz_type` | 业务类型 |
| `biz_id` | 业务侧 ID |
| `handler_code` | 业务回调处理器编码 |
| `external_system` | 外部系统 |
| `external_task_type` | 外部任务类型 |
| `status` | 任务状态 |
| `priority` | 优先级 |
| `start_point_code` | 起点 |
| `end_point_code` | 终点 |
| `vehicle_code` | 载具、架子、托盘、料车等 |
| `callback_status` | 回调状态 |
| `request_payload` | 创建任务扩展参数 |
| `dispatch_payload` | 下发外部系统参数 |
| `result_payload` | 外部反馈参数 |
| `error_msg` | 异常信息 |
### 7.2 task_task_log 日志表
记录每次状态变化、下发、反馈、回调、取消、重试。
关键字段:
| 字段 | 说明 |
| --- | --- |
| `task_id` | 任务 ID |
| `event_type` | CREATE/DISPATCH/FEEDBACK/CALLBACK/CANCEL/RETRY |
| `from_status` | 原状态 |
| `to_status` | 新状态 |
| `request_json` | 请求参数 |
| `response_json` | 响应参数 |
| `success` | 是否成功 |
| `error_msg` | 错误信息 |
### 7.3 task_callback_log 回调日志表
用于保证业务回调幂等和补偿。
| 字段 | 说明 |
| --- | --- |
| `task_id` | 任务 ID |
| `owner_service` | LMS/WMS |
| `handler_code` | 业务处理器编码 |
| `event_type` | FINISH/CANCEL/EXECUTING |
| `status` | PROCESSING/SUCCESS/FAILED |
| `retry_count` | 重试次数 |
| `error_msg` | 失败原因 |
## 8. 状态机设计
推荐 Task 服务状态:
| 状态 | 含义 |
| --- | --- |
| `CREATED` | 已创建 |
| `READY` | 可下发 |
| `ISSUING` | 下发中 |
| `ISSUED` | 已下发 |
| `EXECUTING` | 外部执行中 |
| `FINISHED_PENDING_CALLBACK` | 外部完成,等待业务完成回调 |
| `FINISHED` | 业务完成后最终完成 |
| `CANCEL_PENDING_EXTERNAL` | 等待外部系统取消 |
| `CANCEL_PENDING_CALLBACK` | 外部取消成功,等待业务取消回调 |
| `CANCELLED` | 业务取消后最终取消 |
| `FAILED` | 失败 |
核心原则:
```text
外部系统完成 != 业务完成
外部系统取消 != 业务取消完成
```
因此必须有 `PENDING_CALLBACK` 中间状态。
## 9. 接口设计
### 9.1 Task 创建接口
```text
POST /rpc-api/task/create
```
请求核心字段:
```json
{
"ownerService": "LMS",
"bizType": "PRODUCTION_TRANSFER",
"bizId": "LMS-BIZ-10001",
"handlerCode": "LMS_RACK_TO_STATION",
"externalSystem": "AGV",
"externalTaskType": "MOVE",
"startPointCode": "CACHE_A01",
"endPointCode": "STATION_01",
"vehicleCode": "RACK_001",
"priority": 1,
"requestPayload": {}
}
```
WMS 入库示例:
```json
{
"ownerService": "WMS",
"bizType": "INBOUND",
"bizId": "IN-DIS-10001",
"handlerCode": "WMS_INBOUND_STACKER",
"externalSystem": "STACKER",
"externalTaskType": "INBOUND",
"startPointCode": "IN_PORT_01",
"endPointCode": "A010101",
"vehicleCode": "PALLET_001",
"priority": 5,
"requestPayload": {}
}
```
### 9.2 外部系统反馈接口
```text
POST /api/task/feedback
```
```json
{
"taskId": 10001,
"externalTaskNo": "ACS-TASK-001",
"externalEventId": "EVT-001",
"status": "FINISHED",
"payload": {}
}
```
### 9.3 取消任务接口
```text
POST /rpc-api/task/cancel
```
```json
{
"taskId": 10001,
"reason": "人工取消"
}
```
### 9.4 业务回调接口
第一阶段建议 RPC同步调用业务服务
```text
POST /rpc-api/lms/task-callback/handle
POST /rpc-api/wms/task-callback/handle
```
```json
{
"taskId": 10001,
"taskNo": "T202607130001",
"eventType": "FINISH",
"bizType": "PRODUCTION_TRANSFER",
"bizId": "LMS-BIZ-10001",
"handlerCode": "LMS_RACK_TO_STATION",
"payload": {}
}
```
## 10. Task 服务核心代码抽象
### 10.1 外部系统下发器
```java
public interface ExternalTaskDispatcher {
String getExternalSystem();
DispatchResult dispatch(TaskDO task);
CancelExternalResult cancelExternal(TaskDO task);
}
```
实现示例:
```text
AgvTaskDispatcher
AcsTaskDispatcher
WcsTaskDispatcher
StackerTaskDispatcher
```
Task 服务根据 `external_system` 选择对应 dispatcher。
### 10.2 业务回调通知器
```java
public interface TaskBizCallbackNotifier {
CallbackResult notifyFinish(TaskDO task);
CallbackResult notifyCancel(TaskDO task);
CallbackResult notifyExecuting(TaskDO task);
}
```
第一阶段可实现为 RPC
```text
RpcTaskBizCallbackNotifier
```
第二阶段可实现为 MQ
```text
MqTaskBizCallbackNotifier
```
## 11. LMS/WMS 业务回调 handler 设计
业务服务内部定义:
```java
public interface TaskBizCallbackHandler {
String getHandlerCode();
void onTaskFinished(TaskCallbackRequest request);
void onTaskCancelled(TaskCallbackRequest request);
default void onTaskExecuting(TaskCallbackRequest request) {}
}
```
LMS 示例:
```java
@Component
public class LmsRackToStationCallbackHandler implements TaskBizCallbackHandler {
@Override
public String getHandlerCode() {
return "LMS_RACK_TO_STATION";
}
@Override
public void onTaskFinished(TaskCallbackRequest request) {
// 更新生产搬运记录完成
// 更新架子当前位置
// 释放起点占用
// 占用目标站点或更新目标站点状态
}
@Override
public void onTaskCancelled(TaskCallbackRequest request) {
// 回滚生产搬运记录
// 释放目标站点锁定
// 恢复架子原状态
}
}
```
WMS 示例:
```java
@Component
public class WmsInboundStackerCallbackHandler implements TaskBizCallbackHandler {
@Override
public String getHandlerCode() {
return "WMS_INBOUND_STACKER";
}
@Override
public void onTaskFinished(TaskCallbackRequest request) {
// 入库确认
// 更新库存
// 更新库位状态
// 更新入库单和分配明细
}
@Override
public void onTaskCancelled(TaskCallbackRequest request) {
// 回滚入库分配
// 释放库位预占
// 恢复入库单状态
}
}
```
业务服务内建立分发器:
```java
@Service
public class TaskBizCallbackDispatcher {
private final Map<String, TaskBizCallbackHandler> handlerMap;
public void dispatch(TaskCallbackRequest request) {
TaskBizCallbackHandler handler = handlerMap.get(request.getHandlerCode());
if (handler == null) {
throw new IllegalArgumentException("未找到处理器:" + request.getHandlerCode());
}
if ("FINISH".equals(request.getEventType())) {
handler.onTaskFinished(request);
} else if ("CANCEL".equals(request.getEventType())) {
handler.onTaskCancelled(request);
} else if ("EXECUTING".equals(request.getEventType())) {
handler.onTaskExecuting(request);
}
}
}
```
## 12. 典型流程
### 12.1 LMS 生产搬运任务
```text
LMS 判断架子 RACK_001 要去 STATION_01
-> LMS 锁定目标站点
-> LMS 创建生产搬运业务记录
-> LMS 调用 Task.createTaskhandler_code = LMS_RACK_TO_STATION
-> Task 下发 AGV
-> AGV 反馈执行中Task 更新 EXECUTING可选通知 LMS
-> AGV 反馈完成Task 更新 FINISHED_PENDING_CALLBACK
-> Task 回调 LMS
-> LMS 更新架子位置、站点状态、业务记录完成
-> Task 更新 FINISHED
```
### 12.2 WMS 入库任务
```text
WMS 入库单分配库位 A010101
-> WMS 锁定库位,生成入库分配
-> WMS 调用 Task.createTaskhandler_code = WMS_INBOUND_STACKER
-> Task 下发堆垛机/AGV
-> 外部系统反馈完成
-> Task 更新 FINISHED_PENDING_CALLBACK
-> Task 回调 WMS
-> WMS 确认入库、更新库存、更新库位、更新单据
-> Task 更新 FINISHED
```
### 12.3 取消任务
```text
用户取消任务
-> Task 判断状态
-> 如果已下发,调用外部系统取消
-> 外部取消成功后 Task 更新 CANCEL_PENDING_CALLBACK
-> Task 回调 LMS/WMS
-> LMS/WMS 执行业务回滚
-> Task 更新 CANCELLED
```
## 13. 幂等与事务
### 13.1 Task 幂等
外部反馈按以下维度幂等:
```text
task_id + external_event_id + status
```
同一个完成反馈不能重复触发业务完成。
### 13.2 业务幂等
LMS/WMS 按以下维度幂等:
```text
task_id + event_type
```
如果业务回调已经成功,再次收到直接返回成功。
### 13.3 跨服务一致性
不做分布式事务,采用最终一致性:
1. Task 更新为 `PENDING_CALLBACK`
2. Task 调用 LMS/WMS
3. LMS/WMS 在本地事务内完成业务更新和回调日志;
4. Task 更新最终状态;
5. 失败则进入重试或人工补偿。
## 14. 开发落地步骤
### 第一阶段:基础 RPC 版本
1.`task-api` 定义任务创建、取消、回调 DTO
2.`task-server` 建任务主表、任务日志表、回调日志表;
3. 实现 Task 创建接口;
4. 实现 `ExternalTaskDispatcher` 和 AGV/ACS/堆垛机下发器;
5. 实现外部反馈接口;
6. 实现 RPC 业务回调通知器;
7. 在 LMS/WMS 实现 `TaskBizCallbackHandler` 和分发器;
8. 打通 LMS 生产搬运和 WMS 入库两个典型任务。
### 第二阶段:增强可靠性
1. 增加回调失败重试定时任务;
2. 增加外部下发失败重试;
3. 增加人工补偿页面;
4. 增加状态流转校验;
5. 增加任务日志和链路追踪。
### 第三阶段MQ 演进
1. Task 服务发布任务完成/取消事件;
2. LMS/WMS 消费事件执行业务;
3. 业务服务回调 Task 确认处理结果;
4. RPC 和 MQ 可按任务类型配置切换。
## 15. 最终建议
不要把 LMS/WMS 的业务 `xxxTask` 子类放到 Task 服务,也不要让 Task 服务依赖 LMS/WMS server。
推荐把旧 `AbstractAcsTask` 拆成:
```text
Task 服务ExternalTaskDispatcher负责外部系统下发和取消
LMS/WMSTaskBizCallbackHandler负责业务完成和业务取消
```
`handle_class` 改为:
```text
owner_service + handler_code
```
这样既保留了旧版“不同任务走不同处理器”的扩展性,又满足新架构下服务边界清晰、依赖方向正确、任务服务通用化的目标。