fix(flow): 修复边缘节点执行目标配置验证和解析问题

- 在 EdgeCameraOperateService 中启用视频录制功能并移除硬编码路径
- 为 FlowRuntimeAssignmentResolver 添加节点类型检查避免非边缘节点处理
- 当执行目标为空且运行时分配存在时抛出异常提供明确错误信息
- 在 FlowRuntimeDefinitionValidator 中增强节点验证逻辑确保边缘节点配置完整性
- 添加单元测试验证遗留机器人配置和非机器人节点处理场景
- 修复测试用例中的节点类型配置确保测试准确性
This commit is contained in:
lixiaolong 2026-08-11 17:32:10 +08:00
parent 34ff31366d
commit 18c4d3c0d7
4 changed files with 51 additions and 6 deletions

View File

@ -17,10 +17,17 @@ import java.util.List;
public class FlowRuntimeAssignmentResolver {
public void resolveNode(FlowNodeWrapper node, TaskNodeExecuteMessage message) {
JSONObject executionTarget = node.getRawProperties().getJSONObject("executionTarget");
if (executionTarget == null) {
JSONObject properties = node.getRawProperties();
if (properties == null || !"EDGE".equalsIgnoreCase(properties.getString("nodeType"))) {
return;
}
JSONObject executionTarget = properties.getJSONObject("executionTarget");
if (executionTarget == null) {
if (message.getRuntimeAssignments() == null || message.getRuntimeAssignments().isEmpty()) {
return;
}
throw new GlobalException("节点[" + node.getNodeName() + "]未配置机器人角色");
}
String roleKey = executionTarget.getString("roleKey");
if (StrUtil.isBlank(roleKey)) {

View File

@ -87,11 +87,17 @@ public class FlowRuntimeDefinitionValidator {
for (int i = 0; i < nodes.size(); i++) {
JSONObject node = nodes.getJSONObject(i);
JSONObject properties = node.getJSONObject("properties");
JSONObject target = properties == null ? null : properties.getJSONObject("executionTarget");
if (target == null) {
if (properties == null || !"EDGE".equalsIgnoreCase(properties.getString("nodeType"))) {
continue;
}
JSONObject target = properties.getJSONObject("executionTarget");
if (target == null) {
throw new GlobalException("节点[" + properties.getString("name") + "]未配置机器人角色");
}
String roleKey = target.getString("roleKey");
if (StrUtil.isBlank(roleKey)) {
throw new GlobalException("节点[" + properties.getString("name") + "]未配置机器人角色");
}
Set<String> slotKeys = slotKeysByRole.get(roleKey);
if (slotKeys == null) {
throw new GlobalException("节点[" + properties.getString("name") + "]引用了不存在的机器人角色");

View File

@ -106,9 +106,9 @@ public class EdgeCameraOperateService implements EdgeOperateService {
case CAMERA_RECORDING_START: {
// 生成视频路径
// String videoUrl = edgeCameraService.startRecording(edgeCommonVO);
String videoUrl = edgeCameraService.startRecording(edgeCommonVO);
// String videoUrl = StrUtil.format("{}/{}_{}.mp4", "/home/share/assets/video", deviceId, System.currentTimeMillis());
String videoUrl = "/home/xtkuang/Projects/models/assets/video/IMG_0524_silent.mp4";
// String videoUrl = "/home/xtkuang/Projects/models/assets/video/IMG_0524_silent.mp4";
// 创建一个新的 JSONObject 来保存视频路径和其他信息
JSONObject videoInfo = new JSONObject();
videoInfo.put("videoUrl", videoUrl);

View File

@ -12,6 +12,7 @@ import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
public class FlowRuntimeAssignmentResolverTest {
@ -23,6 +24,7 @@ public class FlowRuntimeAssignmentResolverTest {
node.setNodeName("拍摄");
node.setRawProperties(JSON.parseObject("""
{
"nodeType": "EDGE",
"executionTarget": {
"roleKey": "inspection",
"deviceSlotKey": "front_camera"
@ -55,6 +57,7 @@ public class FlowRuntimeAssignmentResolverTest {
FlowNodeWrapper node = new FlowNodeWrapper();
node.setNodeName("旧节点");
node.setRawProperties(new JSONObject(Map.of(
"nodeType", "EDGE",
"executionTarget", new JSONObject(Map.of("roleKey", "default_executor"))
)));
TaskNodeExecuteMessage message = new TaskNodeExecuteMessage();
@ -65,4 +68,33 @@ public class FlowRuntimeAssignmentResolverTest {
assertEquals("default_executor", message.getRoleKey());
assertEquals("legacy-robot", message.getRobotId());
}
@Test
public void keepsLegacyRobotWhenExecutionTargetIsAbsent() {
FlowNodeWrapper node = new FlowNodeWrapper();
node.setNodeName("旧机器人节点");
node.setRawProperties(new JSONObject(Map.of("nodeType", "EDGE")));
TaskNodeExecuteMessage message = new TaskNodeExecuteMessage();
message.setRobotId("legacy-robot");
resolver.resolveNode(node, message);
assertEquals("legacy-robot", message.getRobotId());
assertNull(message.getRoleKey());
}
@Test
public void ignoresStaleExecutionTargetOnNonRobotNode() {
FlowNodeWrapper node = new FlowNodeWrapper();
node.setNodeName("睡眠");
node.setRawProperties(new JSONObject(Map.of(
"executionTarget", new JSONObject()
)));
TaskNodeExecuteMessage message = new TaskNodeExecuteMessage();
resolver.resolveNode(node, message);
assertNull(message.getRoleKey());
assertNull(message.getResolvedDeviceBindings());
}
}