feat: 完善用户确认节点选项与输出流转
- 重构确认节点单选多选配置及输出参数契约 - 统一管理端、用户中心、匿名分享和公共接口恢复流程 - 增加保存校验、错误契约及交互测试
This commit is contained in:
@@ -18,6 +18,7 @@ import tech.easyflow.ai.easyagentsflow.entity.WorkflowCheckStage;
|
||||
import tech.easyflow.ai.easyagentsflow.service.TinyFlowService;
|
||||
import tech.easyflow.ai.easyagentsflow.service.WorkflowCheckService;
|
||||
import tech.easyflow.ai.easyagentsflow.service.WorkflowRunningParameterResolver;
|
||||
import tech.easyflow.ai.easyagentsflow.service.WorkflowResumeService;
|
||||
import tech.easyflow.ai.easyagentsflow.support.PublishedWorkflowDefinitionIds;
|
||||
import tech.easyflow.ai.easyagentsflow.upload.WorkflowApiPreparedUpload;
|
||||
import tech.easyflow.ai.easyagentsflow.upload.WorkflowApiUploadLifecycleService;
|
||||
@@ -70,6 +71,8 @@ public class PublicWorkflowController {
|
||||
@Resource
|
||||
private WorkflowRunningParameterResolver workflowRunningParameterResolver;
|
||||
@Resource
|
||||
private WorkflowResumeService workflowResumeService;
|
||||
@Resource
|
||||
private WorkflowApiPermissionService workflowApiPermissionService;
|
||||
@Resource
|
||||
private WorkflowExecResultService workflowExecResultService;
|
||||
@@ -250,14 +253,7 @@ public class PublicWorkflowController {
|
||||
SysApiKey apiKey = workflowApiPermissionService.assertWorkflowApi(request.getHeader("ApiKey"), request.getRequestURI());
|
||||
WorkflowExecResult execResult = assertApiKeyExecutionOwnership(apiKey, executeId);
|
||||
assertWorkflowExecutionResumable(execResult);
|
||||
if (!chainExecutor.resumeAsyncIfSuspended(
|
||||
executeId,
|
||||
confirmParams)) {
|
||||
throw new BusinessException(
|
||||
409,
|
||||
40901,
|
||||
"当前执行状态不可恢复,仅暂停中的工作流允许恢复");
|
||||
}
|
||||
workflowResumeService.resume(executeId, confirmParams);
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
|
||||
@@ -394,6 +394,7 @@ public final class WorkflowRunAsyncErrorProfile
|
||||
*/
|
||||
private boolean isStableBusinessCode(int code) {
|
||||
return (code >= 40011 && code <= 40017)
|
||||
|| code == 40031
|
||||
|| (code >= 40101 && code <= 40103)
|
||||
|| (code >= 40301 && code <= 40302)
|
||||
|| (code >= 40401 && code <= 40402)
|
||||
@@ -412,7 +413,8 @@ public final class WorkflowRunAsyncErrorProfile
|
||||
* @return 对外 HTTP 状态
|
||||
*/
|
||||
private int normalizeHttpStatus(int code, int fallback) {
|
||||
if (code >= 40011 && code <= 40017) {
|
||||
if ((code >= 40011 && code <= 40017)
|
||||
|| code == 40031) {
|
||||
return 400;
|
||||
}
|
||||
if (code >= 40101 && code <= 40103) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.springframework.test.util.ReflectionTestUtils;
|
||||
import tech.easyflow.ai.easyagentsflow.entity.ChainInfo;
|
||||
import tech.easyflow.ai.easyagentsflow.entity.NodeInfo;
|
||||
import tech.easyflow.ai.easyagentsflow.service.TinyFlowService;
|
||||
import tech.easyflow.ai.easyagentsflow.service.WorkflowResumeService;
|
||||
import tech.easyflow.ai.entity.Workflow;
|
||||
import tech.easyflow.ai.entity.WorkflowExecResult;
|
||||
import tech.easyflow.ai.enums.PublishStatus;
|
||||
@@ -44,6 +45,7 @@ public class PublicWorkflowControllerBehaviorTest {
|
||||
|
||||
private PublicWorkflowController controller;
|
||||
private ChainExecutor chainExecutor;
|
||||
private WorkflowResumeService workflowResumeService;
|
||||
private TinyFlowService tinyFlowService;
|
||||
private HttpServletRequest request;
|
||||
|
||||
@@ -54,6 +56,7 @@ public class PublicWorkflowControllerBehaviorTest {
|
||||
public void setUp() {
|
||||
controller = new PublicWorkflowController();
|
||||
chainExecutor = Mockito.mock(ChainExecutor.class);
|
||||
workflowResumeService = Mockito.mock(WorkflowResumeService.class);
|
||||
tinyFlowService = Mockito.mock(TinyFlowService.class);
|
||||
WorkflowApiPermissionService permissionService =
|
||||
Mockito.mock(WorkflowApiPermissionService.class);
|
||||
@@ -79,6 +82,10 @@ public class PublicWorkflowControllerBehaviorTest {
|
||||
controller,
|
||||
"chainExecutor",
|
||||
chainExecutor);
|
||||
ReflectionTestUtils.setField(
|
||||
controller,
|
||||
"workflowResumeService",
|
||||
workflowResumeService);
|
||||
ReflectionTestUtils.setField(
|
||||
controller,
|
||||
"tinyFlowService",
|
||||
@@ -108,10 +115,12 @@ public class PublicWorkflowControllerBehaviorTest {
|
||||
public void resumeShouldRejectNonSuspendedExecution() {
|
||||
when(request.getRequestURI()).thenReturn(
|
||||
"/public-api/workflow/resume");
|
||||
when(chainExecutor.resumeAsyncIfSuspended(
|
||||
EXECUTE_ID,
|
||||
Map.of("approved", true)))
|
||||
.thenReturn(false);
|
||||
Mockito.doThrow(new BusinessException(
|
||||
409,
|
||||
40901,
|
||||
"当前执行状态不可恢复,仅暂停中的工作流允许恢复"))
|
||||
.when(workflowResumeService)
|
||||
.resume(EXECUTE_ID, Map.of("approved", true));
|
||||
|
||||
try {
|
||||
controller.resume(
|
||||
@@ -124,7 +133,7 @@ public class PublicWorkflowControllerBehaviorTest {
|
||||
Assert.assertEquals(40901, exception.getErrorCode());
|
||||
}
|
||||
|
||||
verify(chainExecutor).resumeAsyncIfSuspended(
|
||||
verify(workflowResumeService).resume(
|
||||
EXECUTE_ID,
|
||||
Map.of("approved", true));
|
||||
}
|
||||
|
||||
@@ -167,6 +167,28 @@ public class WorkflowRunAsyncErrorProfileTest {
|
||||
resolution.modelAndView.getModel().get("message"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证确认节点恢复校验保留专用错误码,不回退为运行参数错误。
|
||||
*/
|
||||
@Test
|
||||
public void shouldKeepResumeValidationCode() {
|
||||
Resolution resolution = resolve(
|
||||
"/public-api/workflow/resume",
|
||||
MediaType.APPLICATION_JSON_VALUE,
|
||||
new BusinessException(
|
||||
400,
|
||||
40031,
|
||||
"确认参数[模板类型]包含未配置选项"));
|
||||
|
||||
Assert.assertEquals(400, resolution.response.getStatus());
|
||||
Assert.assertEquals(
|
||||
40031,
|
||||
resolution.modelAndView.getModel().get("errorCode"));
|
||||
Assert.assertEquals(
|
||||
"确认参数[模板类型]包含未配置选项",
|
||||
resolution.modelAndView.getModel().get("message"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证 API Key 无效和两层权限错误保持可区分。
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user