632 lines
15 KiB
Markdown
632 lines
15 KiB
Markdown
|
|
# Task 服务创建任务与外部系统下发参数转换设计方案
|
|||
|
|
|
|||
|
|
## 1. 问题背景
|
|||
|
|
|
|||
|
|
旧版 LMS 中,类似 `StockAreaCallTubeTask` 这样的任务子类会实现:
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
public List<AcsTaskDto> addTask()
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
旧版 `addTask` 的核心职责是:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
查询 SCH_BASE_Task
|
|||
|
|
-> 读取任务字段、request_param、point_code、vehicle_code 等
|
|||
|
|
-> 组装 AcsTaskDto
|
|||
|
|
-> 下发 ACS
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
也就是说,在旧架构中:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
业务任务创建、任务表保存、外部系统 DTO 组装、ACS 下发
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
都在 LMS 内的具体 `xxxTask` 子类中完成。
|
|||
|
|
|
|||
|
|
新架构中,`Task` 服务独立出来:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
LMS/WMS
|
|||
|
|
-> 调用 Task 服务创建任务
|
|||
|
|
Task 服务
|
|||
|
|
-> 保存任务
|
|||
|
|
-> 下发外部系统
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
此时会遇到一个关键问题:
|
|||
|
|
|
|||
|
|
> LMS/WMS 创建任务时,传给 Task 服务的是业务任务信息,不一定已经是 `AcsTaskDto`。但 Task 服务下发 ACS 时需要 `AcsTaskDto` 或类似外部系统 DTO。这个转换逻辑应该放在哪里?
|
|||
|
|
|
|||
|
|
如果让 LMS/WMS 直接传 `AcsTaskDto`,会有两个问题:
|
|||
|
|
|
|||
|
|
1. `AcsTaskDto` 是外部系统下发模型,不适合作为业务创建任务模型;
|
|||
|
|
2. Task 服务还需要保存标准任务表,不能只保存一个外部 DTO。
|
|||
|
|
|
|||
|
|
因此需要重新设计“创建任务模型”和“下发模型”的边界。
|
|||
|
|
|
|||
|
|
## 2. 核心结论
|
|||
|
|
|
|||
|
|
建议将旧版 `addTask` 拆成两部分:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
LMS/WMS:负责构建业务任务创建请求 TaskCreateReqDTO
|
|||
|
|
Task 服务:负责保存标准任务数据,并在下发前转换成外部系统 DTO
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
也就是说:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
业务服务不要直接传 AcsTaskDto
|
|||
|
|
Task 服务不要依赖 LMS/WMS 业务类
|
|||
|
|
双方通过标准 TaskCreateReqDTO 交互
|
|||
|
|
Task 服务内部通过 ExternalTaskPayloadBuilder 构建 AcsTaskDto
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
推荐架构:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
LMS/WMS
|
|||
|
|
-> TaskCreateReqDTO 标准创建请求
|
|||
|
|
Task 服务
|
|||
|
|
-> 保存 task_task 标准字段
|
|||
|
|
-> 保存 request_payload 扩展字段
|
|||
|
|
-> 根据 external_system + external_task_type + dispatch_template_code 选择构建器
|
|||
|
|
-> 转换为 AcsTaskDto / WcsTaskDto / StackerTaskDto
|
|||
|
|
-> 下发外部系统
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 3. 新旧职责对照
|
|||
|
|
|
|||
|
|
| 职责 | 旧版 | 新版 |
|
|||
|
|
| --- | --- | --- |
|
|||
|
|
| 业务校验 | `xxxTask#createTask` | LMS/WMS 业务服务 |
|
|||
|
|
| 任务保存 | LMS `SCH_BASE_Task` | Task 服务 `task_task` |
|
|||
|
|
| 业务回调定位 | `handle_class` | `owner_service + handler_code` |
|
|||
|
|
| 外部 DTO 组装 | `xxxTask#addTask` | Task 服务 `ExternalTaskPayloadBuilder` |
|
|||
|
|
| 外部系统下发 | `AbstractAcsTask#notifyAcs` | Task 服务 `ExternalTaskDispatcher` |
|
|||
|
|
| 完成/取消业务逻辑 | `xxxTask#updateTaskStatus` | LMS/WMS `TaskBizCallbackHandler` |
|
|||
|
|
|
|||
|
|
## 4. 为什么不建议 LMS/WMS 直接传 AcsTaskDto
|
|||
|
|
|
|||
|
|
不建议让 LMS/WMS 创建任务时直接传 `AcsTaskDto`,原因如下:
|
|||
|
|
|
|||
|
|
### 4.1 业务创建模型和外部下发模型不是一回事
|
|||
|
|
|
|||
|
|
业务创建任务时关心的是:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
我要搬什么
|
|||
|
|
从哪里搬
|
|||
|
|
搬到哪里
|
|||
|
|
归属哪个业务
|
|||
|
|
完成后回调哪个 handler
|
|||
|
|
业务扩展参数是什么
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
外部系统下发时关心的是:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
ACS task_type
|
|||
|
|
start_device_code
|
|||
|
|
next_device_code
|
|||
|
|
vehicle_code
|
|||
|
|
agv_system_type
|
|||
|
|
route_plan_code
|
|||
|
|
interaction_json
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
两者不应该强耦合。
|
|||
|
|
|
|||
|
|
### 4.2 Task 服务需要标准化保存任务
|
|||
|
|
|
|||
|
|
Task 服务需要保存:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
task_id
|
|||
|
|
task_no
|
|||
|
|
owner_service
|
|||
|
|
biz_type
|
|||
|
|
biz_id
|
|||
|
|
handler_code
|
|||
|
|
external_system
|
|||
|
|
status
|
|||
|
|
start_point_code
|
|||
|
|
end_point_code
|
|||
|
|
vehicle_code
|
|||
|
|
request_payload
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
如果只收到 `AcsTaskDto`,Task 服务会丢失业务归属、回调 handler、业务 ID 等关键字段。
|
|||
|
|
|
|||
|
|
### 4.3 外部系统 DTO 可能变化
|
|||
|
|
|
|||
|
|
未来可能不止 ACS:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
ACS
|
|||
|
|
WCS
|
|||
|
|
AGV
|
|||
|
|
STACKER
|
|||
|
|
PLC
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
如果业务服务直接构建外部 DTO,会导致业务服务感知所有外部系统协议,不利于统一下发和协议升级。
|
|||
|
|
|
|||
|
|
## 5. 推荐数据模型
|
|||
|
|
|
|||
|
|
### 5.1 TaskCreateReqDTO
|
|||
|
|
|
|||
|
|
LMS/WMS 调用 Task 服务创建任务时,传标准创建请求。
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
@Data
|
|||
|
|
public class TaskCreateReqDTO {
|
|||
|
|
private String ownerService;
|
|||
|
|
private String bizType;
|
|||
|
|
private String bizId;
|
|||
|
|
private String handlerCode;
|
|||
|
|
|
|||
|
|
private String externalSystem;
|
|||
|
|
private String externalTaskType;
|
|||
|
|
private String dispatchTemplateCode;
|
|||
|
|
|
|||
|
|
private String startPointCode;
|
|||
|
|
private String endPointCode;
|
|||
|
|
private String startPointCode2;
|
|||
|
|
private String endPointCode2;
|
|||
|
|
|
|||
|
|
private String vehicleCode;
|
|||
|
|
private String vehicleCode2;
|
|||
|
|
private Integer priority;
|
|||
|
|
private String productArea;
|
|||
|
|
|
|||
|
|
private Map<String, Object> requestPayload;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
字段说明:
|
|||
|
|
|
|||
|
|
| 字段 | 说明 |
|
|||
|
|
| --- | --- |
|
|||
|
|
| `ownerService` | LMS/WMS,决定完成取消回调发给谁 |
|
|||
|
|
| `bizType` | 业务类型,例如 `STOCK_AREA_CALL_TUBE` |
|
|||
|
|
| `bizId` | 业务侧 ID |
|
|||
|
|
| `handlerCode` | 业务回调 handler 编码 |
|
|||
|
|
| `externalSystem` | 外部系统,例如 ACS/WCS/STACKER |
|
|||
|
|
| `externalTaskType` | 外部系统任务类型 |
|
|||
|
|
| `dispatchTemplateCode` | 下发参数构建模板编码 |
|
|||
|
|
| `startPointCode` | 起点 |
|
|||
|
|
| `endPointCode` | 终点 |
|
|||
|
|
| `vehicleCode` | 载具、架子、托盘等 |
|
|||
|
|
| `requestPayload` | 扩展参数 |
|
|||
|
|
|
|||
|
|
### 5.2 TaskDO 保存字段
|
|||
|
|
|
|||
|
|
Task 服务保存标准字段和扩展 JSON:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
id
|
|||
|
|
task_no
|
|||
|
|
owner_service
|
|||
|
|
biz_type
|
|||
|
|
biz_id
|
|||
|
|
handler_code
|
|||
|
|
external_system
|
|||
|
|
external_task_type
|
|||
|
|
dispatch_template_code
|
|||
|
|
start_point_code
|
|||
|
|
end_point_code
|
|||
|
|
start_point_code2
|
|||
|
|
end_point_code2
|
|||
|
|
vehicle_code
|
|||
|
|
vehicle_code2
|
|||
|
|
priority
|
|||
|
|
product_area
|
|||
|
|
status
|
|||
|
|
request_payload
|
|||
|
|
dispatch_payload
|
|||
|
|
result_payload
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 6. 下发参数转换设计
|
|||
|
|
|
|||
|
|
### 6.1 定义统一构建器接口
|
|||
|
|
|
|||
|
|
Task 服务内部定义:
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
public interface ExternalTaskPayloadBuilder<T> {
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 外部系统,例如 ACS/WCS/STACKER
|
|||
|
|
*/
|
|||
|
|
String getExternalSystem();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 下发模板编码,例如 STOCK_AREA_CALL_TUBE
|
|||
|
|
*/
|
|||
|
|
String getDispatchTemplateCode();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 根据 TaskDO 构建外部系统 DTO
|
|||
|
|
*/
|
|||
|
|
T build(TaskDO task);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 6.2 ACS 纸管搬运构建器
|
|||
|
|
|
|||
|
|
旧版 `StockAreaCallTubeTask#addTask` 逻辑迁移到 Task 服务的构建器中。
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
@Component
|
|||
|
|
public class AcsStockAreaCallTubePayloadBuilder implements ExternalTaskPayloadBuilder<AcsTaskDto> {
|
|||
|
|
|
|||
|
|
@Override
|
|||
|
|
public String getExternalSystem() {
|
|||
|
|
return "ACS";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@Override
|
|||
|
|
public String getDispatchTemplateCode() {
|
|||
|
|
return "STOCK_AREA_CALL_TUBE";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@Override
|
|||
|
|
public AcsTaskDto build(TaskDO task) {
|
|||
|
|
Map<String, Object> payload = task.getRequestPayloadMap();
|
|||
|
|
|
|||
|
|
return AcsTaskDto.builder()
|
|||
|
|
.extTaskId(String.valueOf(task.getId()))
|
|||
|
|
.taskCode(task.getTaskNo())
|
|||
|
|
.taskType(task.getExternalTaskType())
|
|||
|
|
.startDeviceCode(task.getStartPointCode())
|
|||
|
|
.nextDeviceCode(task.getEndPointCode())
|
|||
|
|
.startDeviceCode2(task.getStartPointCode2())
|
|||
|
|
.nextDeviceCode2(task.getEndPointCode2())
|
|||
|
|
.vehicleCode(task.getVehicleCode())
|
|||
|
|
.interactionJson(payload)
|
|||
|
|
.agvSystemType("2")
|
|||
|
|
.priority(String.valueOf(task.getPriority()))
|
|||
|
|
.productArea(task.getProductArea())
|
|||
|
|
.build();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
对应旧版逻辑:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
StockAreaCallTubeTask#addTask
|
|||
|
|
-> 查询任务
|
|||
|
|
-> 构建 AcsTaskDto
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
新版变为:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
AcsStockAreaCallTubePayloadBuilder#build
|
|||
|
|
-> 根据 TaskDO 构建 AcsTaskDto
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 6.3 通用 ACS 构建器
|
|||
|
|
|
|||
|
|
如果很多 ACS 任务字段差不多,也可以提供一个通用构建器:
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
@Component
|
|||
|
|
public class AcsDefaultPayloadBuilder implements ExternalTaskPayloadBuilder<AcsTaskDto> {
|
|||
|
|
|
|||
|
|
@Override
|
|||
|
|
public String getExternalSystem() {
|
|||
|
|
return "ACS";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@Override
|
|||
|
|
public String getDispatchTemplateCode() {
|
|||
|
|
return "DEFAULT";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@Override
|
|||
|
|
public AcsTaskDto build(TaskDO task) {
|
|||
|
|
return AcsTaskDto.builder()
|
|||
|
|
.extTaskId(String.valueOf(task.getId()))
|
|||
|
|
.taskCode(task.getTaskNo())
|
|||
|
|
.taskType(task.getExternalTaskType())
|
|||
|
|
.startDeviceCode(task.getStartPointCode())
|
|||
|
|
.nextDeviceCode(task.getEndPointCode())
|
|||
|
|
.vehicleCode(task.getVehicleCode())
|
|||
|
|
.priority(String.valueOf(task.getPriority()))
|
|||
|
|
.productArea(task.getProductArea())
|
|||
|
|
.interactionJson(task.getRequestPayloadMap())
|
|||
|
|
.build();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
特殊任务再单独实现专用 Builder。
|
|||
|
|
|
|||
|
|
## 7. Builder 注册表
|
|||
|
|
|
|||
|
|
Task 服务启动时收集所有 Builder。
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
@Component
|
|||
|
|
public class ExternalTaskPayloadBuilderRegistry {
|
|||
|
|
|
|||
|
|
private final Map<String, ExternalTaskPayloadBuilder<?>> builderMap = new HashMap<>();
|
|||
|
|
|
|||
|
|
public ExternalTaskPayloadBuilderRegistry(List<ExternalTaskPayloadBuilder<?>> builders) {
|
|||
|
|
for (ExternalTaskPayloadBuilder<?> builder : builders) {
|
|||
|
|
String key = buildKey(builder.getExternalSystem(), builder.getDispatchTemplateCode());
|
|||
|
|
if (builderMap.containsKey(key)) {
|
|||
|
|
throw new IllegalStateException("重复的下发参数构建器:" + key);
|
|||
|
|
}
|
|||
|
|
builderMap.put(key, builder);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public ExternalTaskPayloadBuilder<?> getRequiredBuilder(String externalSystem, String dispatchTemplateCode) {
|
|||
|
|
String key = buildKey(externalSystem, dispatchTemplateCode);
|
|||
|
|
ExternalTaskPayloadBuilder<?> builder = builderMap.get(key);
|
|||
|
|
if (builder == null) {
|
|||
|
|
throw new IllegalArgumentException("未找到下发参数构建器:" + key);
|
|||
|
|
}
|
|||
|
|
return builder;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private String buildKey(String externalSystem, String dispatchTemplateCode) {
|
|||
|
|
return externalSystem + ":" + dispatchTemplateCode;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
例如:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
ACS:DEFAULT -> AcsDefaultPayloadBuilder
|
|||
|
|
ACS:STOCK_AREA_CALL_TUBE -> AcsStockAreaCallTubePayloadBuilder
|
|||
|
|
STACKER:INBOUND -> StackerInboundPayloadBuilder
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 8. 外部系统下发器设计
|
|||
|
|
|
|||
|
|
Builder 只负责构建 DTO,下发器负责调用外部系统。
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
public interface ExternalTaskDispatcher {
|
|||
|
|
String getExternalSystem();
|
|||
|
|
DispatchResult dispatch(TaskDO task, Object payload);
|
|||
|
|
CancelExternalResult cancelExternal(TaskDO task);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
ACS 下发器示例:
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
@Component
|
|||
|
|
public class AcsTaskDispatcher implements ExternalTaskDispatcher {
|
|||
|
|
|
|||
|
|
@Override
|
|||
|
|
public String getExternalSystem() {
|
|||
|
|
return "ACS";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@Override
|
|||
|
|
public DispatchResult dispatch(TaskDO task, Object payload) {
|
|||
|
|
AcsTaskDto acsTask = (AcsTaskDto) payload;
|
|||
|
|
// 调用 ACS HTTP 接口
|
|||
|
|
// acsClient.createTask(Collections.singletonList(acsTask));
|
|||
|
|
return DispatchResult.success();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@Override
|
|||
|
|
public CancelExternalResult cancelExternal(TaskDO task) {
|
|||
|
|
// 调用 ACS 取消接口
|
|||
|
|
return CancelExternalResult.success();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 9. Task 下发流程
|
|||
|
|
|
|||
|
|
Task 服务下发任务时:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
1. 查询 READY 状态任务
|
|||
|
|
2. 根据 external_system + dispatch_template_code 找 Builder
|
|||
|
|
3. Builder 根据 TaskDO 构建 AcsTaskDto/WcsTaskDto
|
|||
|
|
4. 保存 dispatch_payload
|
|||
|
|
5. 根据 external_system 找 Dispatcher
|
|||
|
|
6. Dispatcher 调用外部系统
|
|||
|
|
7. 成功后状态改为 ISSUED
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
伪代码:
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
public void dispatchTask(Long taskId) {
|
|||
|
|
TaskDO task = taskMapper.selectById(taskId);
|
|||
|
|
|
|||
|
|
ExternalTaskPayloadBuilder<?> builder = builderRegistry.getRequiredBuilder(
|
|||
|
|
task.getExternalSystem(),
|
|||
|
|
task.getDispatchTemplateCode()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
Object externalPayload = builder.build(task);
|
|||
|
|
task.setDispatchPayload(JsonUtils.toJsonString(externalPayload));
|
|||
|
|
task.setStatus(TaskStatus.ISSUING);
|
|||
|
|
taskMapper.updateById(task);
|
|||
|
|
|
|||
|
|
ExternalTaskDispatcher dispatcher = dispatcherRegistry.getRequiredDispatcher(task.getExternalSystem());
|
|||
|
|
DispatchResult result = dispatcher.dispatch(task, externalPayload);
|
|||
|
|
|
|||
|
|
if (result.isSuccess()) {
|
|||
|
|
task.setStatus(TaskStatus.ISSUED);
|
|||
|
|
} else {
|
|||
|
|
task.setStatus(TaskStatus.FAILED);
|
|||
|
|
task.setErrorMsg(result.getMessage());
|
|||
|
|
}
|
|||
|
|
taskMapper.updateById(task);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 10. StockAreaCallTubeTask 新版完整链路
|
|||
|
|
|
|||
|
|
### 10.1 LMS 创建任务
|
|||
|
|
|
|||
|
|
LMS 不传 `AcsTaskDto`,而是传标准 `TaskCreateReqDTO`:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"ownerService": "LMS",
|
|||
|
|
"bizType": "STOCK_AREA_CALL_TUBE",
|
|||
|
|
"bizId": "LMS-BIZ-10001",
|
|||
|
|
"handlerCode": "LMS_STOCK_AREA_CALL_TUBE",
|
|||
|
|
"externalSystem": "ACS",
|
|||
|
|
"externalTaskType": "3",
|
|||
|
|
"dispatchTemplateCode": "STOCK_AREA_CALL_TUBE",
|
|||
|
|
"startPointCode": "STOCK_A01",
|
|||
|
|
"endPointCode": "ROBOT_STOCK_A01",
|
|||
|
|
"startPointCode2": "",
|
|||
|
|
"endPointCode2": "",
|
|||
|
|
"vehicleCode": "TUBE_CAR_001",
|
|||
|
|
"priority": 1,
|
|||
|
|
"productArea": "BLK",
|
|||
|
|
"requestPayload": {
|
|||
|
|
"to_material": "M001,M002"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 10.2 Task 保存任务
|
|||
|
|
|
|||
|
|
Task 保存为标准任务记录:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
owner_service = LMS
|
|||
|
|
handler_code = LMS_STOCK_AREA_CALL_TUBE
|
|||
|
|
external_system = ACS
|
|||
|
|
dispatch_template_code = STOCK_AREA_CALL_TUBE
|
|||
|
|
request_payload = {to_material: ...}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 10.3 Task 下发 ACS
|
|||
|
|
|
|||
|
|
Task 根据:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
external_system = ACS
|
|||
|
|
dispatch_template_code = STOCK_AREA_CALL_TUBE
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
找到:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
AcsStockAreaCallTubePayloadBuilder
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
构建:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
AcsTaskDto
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
再由:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
AcsTaskDispatcher
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
下发 ACS。
|
|||
|
|
|
|||
|
|
### 10.4 ACS 完成后业务回调
|
|||
|
|
|
|||
|
|
ACS 完成后:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
Task 接收反馈
|
|||
|
|
-> 发布 TASK_FINISHED
|
|||
|
|
-> owner_service = LMS
|
|||
|
|
-> handler_code = LMS_STOCK_AREA_CALL_TUBE
|
|||
|
|
-> LMS 消费
|
|||
|
|
-> StockAreaCallTubeTaskHandler#onTaskFinished
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 11. 设计重点
|
|||
|
|
|
|||
|
|
### 11.1 TaskCreateReqDTO 不是 AcsTaskDto
|
|||
|
|
|
|||
|
|
`TaskCreateReqDTO` 是任务服务标准创建模型。
|
|||
|
|
|
|||
|
|
`AcsTaskDto` 是外部系统 ACS 的下发模型。
|
|||
|
|
|
|||
|
|
二者不要混用。
|
|||
|
|
|
|||
|
|
### 11.2 addTask 职责迁移到 Builder
|
|||
|
|
|
|||
|
|
旧版:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
xxxTask#addTask -> AcsTaskDto
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
新版:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
ExternalTaskPayloadBuilder#build -> AcsTaskDto
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 11.3 特殊字段放 request_payload
|
|||
|
|
|
|||
|
|
如果某个任务需要特殊参数,例如:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
interaction_json
|
|||
|
|
route_plan_code
|
|||
|
|
agv_system_type
|
|||
|
|
paper_array
|
|||
|
|
truss_type
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
可以通过两种方式处理:
|
|||
|
|
|
|||
|
|
1. 常用字段提升为 TaskDO 标准字段;
|
|||
|
|
2. 特殊字段放入 `request_payload`,由专用 Builder 读取。
|
|||
|
|
|
|||
|
|
### 11.4 dispatch_template_code 决定怎么转 DTO
|
|||
|
|
|
|||
|
|
同样是 ACS,不同任务可能 DTO 组装方式不同,所以需要:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
external_system + dispatch_template_code
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
联合定位 Builder。
|
|||
|
|
|
|||
|
|
## 12. 最终建议
|
|||
|
|
|
|||
|
|
不要让 LMS/WMS 直接封装 `AcsTaskDto`。
|
|||
|
|
|
|||
|
|
推荐方式是:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
LMS/WMS
|
|||
|
|
-> TaskCreateReqDTO
|
|||
|
|
Task 服务
|
|||
|
|
-> 保存标准任务字段 + request_payload
|
|||
|
|
-> ExternalTaskPayloadBuilder 转换外部 DTO
|
|||
|
|
-> ExternalTaskDispatcher 下发外部系统
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
这样既能让 Task 服务保存标准任务数据,又能保留旧版 `addTask` 对不同任务差异化组装外部 DTO 的能力。
|
|||
|
|
|
|||
|
|
一句话总结:
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
旧 addTask 不放 LMS/WMS,也不让业务服务直接传 AcsTaskDto;
|
|||
|
|
旧 addTask 的 DTO 转换职责迁移到 Task 服务中的 ExternalTaskPayloadBuilder。
|
|||
|
|
```
|