# 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/WMS:BusinessTaskCreator,可选 Task:ExternalTaskDispatcher LMS/WMS:TaskBizCallbackHandler ``` ## 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 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.createTask,handler_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.createTask,handler_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/WMS:TaskBizCallbackHandler,负责业务完成和业务取消 ``` 旧 `handle_class` 改为: ```text owner_service + handler_code ``` 这样既保留了旧版“不同任务走不同处理器”的扩展性,又满足新架构下服务边界清晰、依赖方向正确、任务服务通用化的目标。