From f5fb0a2dae5730391485763ad2cbdcb949d684f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=9A=E8=BE=B0=E5=85=88=E7=94=9F?= Date: Mon, 9 Dec 2024 00:01:46 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=AF=E6=89=A7=E8=A1=8C=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E7=AE=80=E5=8D=95=E7=9A=84=E5=B7=A5=E4=BD=9C=E6=B5=81=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../engine/DefaultWorkflowEngine.java | 28 ++++---- .../exception/WorkflowEngineException.java | 1 - .../executor/node/ScriptNodeExecutor.java | 65 +++++++++--------- .../executor/node/ShellNodeExecutor.java | 8 +-- ...g.java => ApprovalNodeExecutorConfig.java} | 2 +- ....java => ConditionNodeExecutorConfig.java} | 2 +- ...Config.java => GitNodeExecutorConfig.java} | 2 +- ...onfig.java => HttpNodeExecutorConfig.java} | 2 +- ...ig.java => JenkinsNodeExecutorConfig.java} | 2 +- ...nfig.java => NacosNodeExecutorConfig.java} | 2 +- .../executor/node/config/NodeConfig.java | 66 ------------------- .../node/config/NodeExecutorConfig.java | 48 ++++++++++++++ ...fig.java => NotifyNodeExecutorConfig.java} | 2 +- ...g.java => ParallelNodeExecutorConfig.java} | 2 +- ...fig.java => ScriptNodeExecutorConfig.java} | 30 ++++----- ...nfig.java => ShellNodeExecutorConfig.java} | 4 +- .../node/script/command/ScriptCommand.java | 4 +- .../command/impl/PythonScriptCommand.java | 4 +- .../command/impl/ShellScriptCommand.java | 4 +- .../backend/workflow/entity/NodeInstance.java | 63 ++++++++++++++---- .../workflow/entity/WorkflowInstance.java | 10 --- 21 files changed, 176 insertions(+), 175 deletions(-) rename backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/{ApprovalNodeConfig.java => ApprovalNodeExecutorConfig.java} (91%) rename backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/{ConditionNodeConfig.java => ConditionNodeExecutorConfig.java} (91%) rename backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/{GitNodeConfig.java => GitNodeExecutorConfig.java} (92%) rename backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/{HttpNodeConfig.java => HttpNodeExecutorConfig.java} (93%) rename backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/{JenkinsNodeConfig.java => JenkinsNodeExecutorConfig.java} (91%) rename backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/{NacosNodeConfig.java => NacosNodeExecutorConfig.java} (93%) delete mode 100644 backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NodeConfig.java create mode 100644 backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NodeExecutorConfig.java rename backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/{NotifyNodeConfig.java => NotifyNodeExecutorConfig.java} (93%) rename backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/{ParallelNodeConfig.java => ParallelNodeExecutorConfig.java} (92%) rename backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/{ScriptNodeConfig.java => ScriptNodeExecutorConfig.java} (81%) rename backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/{ShellNodeConfig.java => ShellNodeExecutorConfig.java} (85%) diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/DefaultWorkflowEngine.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/DefaultWorkflowEngine.java index f4602ccf..57b2413e 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/DefaultWorkflowEngine.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/DefaultWorkflowEngine.java @@ -124,7 +124,7 @@ public class DefaultWorkflowEngine implements WorkflowEngine { startNode.setNodeType(startNodeConfig.getType()); startNode.setName(startNodeConfig.getName()); startNode.setConfig(objectMapper.writeValueAsString(startNodeConfig.getConfig())); - startNode.setStatus(NodeStatusEnum.PENDING); + startNode.setStatus(NodeStatusEnum.RUNNING); startNode.setCreateTime(LocalDateTime.now()); nodeInstanceRepository.save(startNode); @@ -203,7 +203,6 @@ public class DefaultWorkflowEngine implements WorkflowEngine { .findByWorkflowInstanceAndStatusNot(instance, NodeStatusEnum.COMPLETED); if (uncompletedNodes.isEmpty()) { - instance.complete(); workflowInstanceRepository.save(instance); } } catch (Exception e) { @@ -223,21 +222,18 @@ public class DefaultWorkflowEngine implements WorkflowEngine { } private void createAndExecuteNextNode(WorkflowInstance instance, String nextNodeId, NodeConfig nodeConfig) { - try { - NodeInstance nextNode = new NodeInstance(); - nextNode.setNodeId(nextNodeId); - nextNode.setWorkflowInstance(instance); - nextNode.setNodeType(nodeConfig.getType()); - nextNode.setName(nodeConfig.getName()); - nextNode.setConfig(objectMapper.writeValueAsString(nodeConfig.getConfig())); - nextNode.setStatus(NodeStatusEnum.PENDING); - nodeInstanceRepository.save(nextNode); + NodeInstance nextNode = new NodeInstance(); + nextNode.setNodeId(nextNodeId); + nextNode.setWorkflowInstance(instance); + nextNode.setNodeType(nodeConfig.getType()); + nextNode.setName(nodeConfig.getName()); +// nextNode.setConfigObject(nodeExecuteConfigConverter.toNodeExecutorConfig(nodeConfig)); +// nextNode.setConfigObject(nodeConfig); + nextNode.setStatus(NodeStatusEnum.PENDING); + nodeInstanceRepository.save(nextNode); - // 递归执行后续节点 - executeNode(nextNode.getId()); - } catch (JsonProcessingException e) { - throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_CONFIG_INVALID, e); - } + // 递归执行后续节点 + executeNode(nextNode.getId()); } @Override diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/exception/WorkflowEngineException.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/exception/WorkflowEngineException.java index 7e75aeba..a41e1b73 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/exception/WorkflowEngineException.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/exception/WorkflowEngineException.java @@ -15,6 +15,5 @@ public class WorkflowEngineException extends BusinessException { public WorkflowEngineException(ResponseCode code, Throwable cause) { super(code, new Object[]{cause.getMessage()}); - initCause(cause); } } \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/ScriptNodeExecutor.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/ScriptNodeExecutor.java index 652aea38..7f27ab4b 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/ScriptNodeExecutor.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/ScriptNodeExecutor.java @@ -5,9 +5,10 @@ import com.qqchen.deploy.backend.system.enums.LogLevelEnum; import com.qqchen.deploy.backend.framework.enums.ResponseCode; import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException; import com.qqchen.deploy.backend.workflow.engine.context.WorkflowContextOperations; -import com.qqchen.deploy.backend.workflow.engine.executor.node.config.ScriptNodeConfig; +import com.qqchen.deploy.backend.workflow.engine.executor.node.config.ScriptNodeExecutorConfig; import com.qqchen.deploy.backend.workflow.entity.NodeInstance; import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; +import com.qqchen.deploy.backend.workflow.enums.ScriptLanguageEnum; import com.qqchen.deploy.backend.workflow.service.WorkflowVariableOperations; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -51,7 +52,7 @@ public class ScriptNodeExecutor extends AbstractNodeExecutor { @Override public void validate(String config) { try { - ScriptNodeConfig scriptConfig = objectMapper.readValue(config, ScriptNodeConfig.class); + ScriptNodeExecutorConfig scriptConfig = objectMapper.readValue(config, ScriptNodeExecutorConfig.class); // 验证脚本内容 if (scriptConfig.getScript() == null || scriptConfig.getScript().trim().isEmpty()) { throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_CONFIG_ERROR, "Script content cannot be empty"); @@ -78,40 +79,44 @@ public class ScriptNodeExecutor extends AbstractNodeExecutor { @Override protected void doExecute(NodeInstance nodeInstance, WorkflowContextOperations context) { try { - String configJson = nodeInstance.getConfig(); - ScriptNodeConfig config = objectMapper.readValue(configJson, ScriptNodeConfig.class); - - // 设置重试次数和间隔 - int maxAttempts = config.getRetryTimes() != null ? config.getRetryTimes() : 1; - long retryInterval = config.getRetryInterval() != null ? config.getRetryInterval() : 0; - - Exception lastException = null; - for (int attempt = 1; attempt <= maxAttempts; attempt++) { - try { - // 执行脚本 +// String configJson = nodeInstance.getConfig(); +// ScriptNodeExecutorConfig config = objectMapper.readValue(configJson, ScriptNodeExecutorConfig.class); +// +// // 设置重试次数和间隔 +// int maxAttempts = config.getRetryTimes() != null ? config.getRetryTimes() : 1; +// long retryInterval = config.getRetryInterval() != null ? config.getRetryInterval() : 0; +// +// Exception lastException = null; +// for (int attempt = 1; attempt <= maxAttempts; attempt++) { +// try { +// // 执行脚本 + ScriptNodeExecutorConfig config = new ScriptNodeExecutorConfig(); + config.setLanguage(ScriptLanguageEnum.SHELL); + config.setInterpreter("/bin/bash"); + config.setScript("ls -a"); executeScript(config, nodeInstance, context); - return; // 执行成功,直接返回 - } catch (Exception e) { - lastException = e; - if (attempt < maxAttempts) { - context.log(String.format("Script execution failed (attempt %d/%d), retrying in %d seconds", - attempt, maxAttempts, retryInterval), LogLevelEnum.WARN); - Thread.sleep(retryInterval * 1000L); - } - } - } - - // 如果所有重试都失败,抛出最后一个异常 - if (lastException != null) { - throw lastException; - } - +// return; // 执行成功,直接返回 +// } catch (Exception e) { +// lastException = e; +// if (attempt < maxAttempts) { +// context.log(String.format("Script execution failed (attempt %d/%d), retrying in %d seconds", +// attempt, maxAttempts, retryInterval), LogLevelEnum.WARN); +// Thread.sleep(retryInterval * 1000L); +// } +// } +// } +// +// // 如果所有重试都失败,抛出最后一个异常 +// if (lastException != null) { +// throw lastException; +// } + } catch (Exception e) { throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_EXECUTION_FAILED, e); } } - private void executeScript(ScriptNodeConfig config, NodeInstance nodeInstance, WorkflowContextOperations context) throws Exception { + private void executeScript(ScriptNodeExecutorConfig config, NodeInstance nodeInstance, WorkflowContextOperations context) throws Exception { ProcessBuilder processBuilder = new ProcessBuilder(); // 获取命令实现并构建命令 diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/ShellNodeExecutor.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/ShellNodeExecutor.java index 3e15b8a2..b5332af0 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/ShellNodeExecutor.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/ShellNodeExecutor.java @@ -5,7 +5,7 @@ import com.qqchen.deploy.backend.system.enums.LogLevelEnum; import com.qqchen.deploy.backend.framework.enums.ResponseCode; import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException; import com.qqchen.deploy.backend.workflow.engine.context.WorkflowContextOperations; -import com.qqchen.deploy.backend.workflow.engine.executor.node.config.ShellNodeConfig; +import com.qqchen.deploy.backend.workflow.engine.executor.node.config.ShellNodeExecutorConfig; import com.qqchen.deploy.backend.workflow.entity.NodeInstance; import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; import com.qqchen.deploy.backend.workflow.service.WorkflowVariableOperations; @@ -46,7 +46,7 @@ public class ShellNodeExecutor extends AbstractNodeExecutor { @Override public void validate(String config) { try { - ShellNodeConfig shellConfig = objectMapper.readValue(config, ShellNodeConfig.class); + ShellNodeExecutorConfig shellConfig = objectMapper.readValue(config, ShellNodeExecutorConfig.class); // 验证执行器类型 if (!"SHELL".equals(shellConfig.getExecutor())) { throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_CONFIG_ERROR); @@ -74,7 +74,7 @@ public class ShellNodeExecutor extends AbstractNodeExecutor { protected void doExecute(NodeInstance nodeInstance, WorkflowContextOperations context) { try { String configJson = nodeInstance.getConfig(); - ShellNodeConfig config = objectMapper.readValue(configJson, ShellNodeConfig.class); + ShellNodeExecutorConfig config = objectMapper.readValue(configJson, ShellNodeExecutorConfig.class); // 验证执行器类型 if (!"SHELL".equals(config.getExecutor())) { @@ -110,7 +110,7 @@ public class ShellNodeExecutor extends AbstractNodeExecutor { } } - private void executeShellCommand(ShellNodeConfig config, NodeInstance nodeInstance, WorkflowContextOperations context) throws Exception { + private void executeShellCommand(ShellNodeExecutorConfig config, NodeInstance nodeInstance, WorkflowContextOperations context) throws Exception { ProcessBuilder processBuilder = new ProcessBuilder(); processBuilder.command("sh", "-c", config.getScript()); diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ApprovalNodeConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ApprovalNodeExecutorConfig.java similarity index 91% rename from backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ApprovalNodeConfig.java rename to backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ApprovalNodeExecutorConfig.java index 36c879da..9604c2f3 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ApprovalNodeConfig.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ApprovalNodeExecutorConfig.java @@ -10,7 +10,7 @@ import java.util.List; */ @Data @EqualsAndHashCode(callSuper = true) -public class ApprovalNodeConfig extends NodeConfig { +public class ApprovalNodeExecutorConfig extends NodeExecutorConfig { /** * 审批人类型:USER-指定用户,ROLE-指定角色,LEADER-直属领导 diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ConditionNodeConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ConditionNodeExecutorConfig.java similarity index 91% rename from backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ConditionNodeConfig.java rename to backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ConditionNodeExecutorConfig.java index 58e12285..a11283d2 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ConditionNodeConfig.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ConditionNodeExecutorConfig.java @@ -9,7 +9,7 @@ import java.util.List; */ @Data @EqualsAndHashCode(callSuper = true) -public class ConditionNodeConfig extends NodeConfig { +public class ConditionNodeExecutorConfig extends NodeExecutorConfig { /** * 条件表达式(使用SpEL表达式) diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/GitNodeConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/GitNodeExecutorConfig.java similarity index 92% rename from backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/GitNodeConfig.java rename to backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/GitNodeExecutorConfig.java index 14ceabeb..d4d7f243 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/GitNodeConfig.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/GitNodeExecutorConfig.java @@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode; */ @Data @EqualsAndHashCode(callSuper = true) -public class GitNodeConfig extends NodeConfig { +public class GitNodeExecutorConfig extends NodeExecutorConfig { /** * Git仓库URL diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/HttpNodeConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/HttpNodeExecutorConfig.java similarity index 93% rename from backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/HttpNodeConfig.java rename to backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/HttpNodeExecutorConfig.java index 05df8417..0d0bc6c4 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/HttpNodeConfig.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/HttpNodeExecutorConfig.java @@ -9,7 +9,7 @@ import java.util.Map; */ @Data @EqualsAndHashCode(callSuper = true) -public class HttpNodeConfig extends NodeConfig { +public class HttpNodeExecutorConfig extends NodeExecutorConfig { /** * 请求URL diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/JenkinsNodeConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/JenkinsNodeExecutorConfig.java similarity index 91% rename from backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/JenkinsNodeConfig.java rename to backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/JenkinsNodeExecutorConfig.java index 8167ee5e..9025cba7 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/JenkinsNodeConfig.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/JenkinsNodeExecutorConfig.java @@ -9,7 +9,7 @@ import java.util.Map; */ @Data @EqualsAndHashCode(callSuper = true) -public class JenkinsNodeConfig extends NodeConfig { +public class JenkinsNodeExecutorConfig extends NodeExecutorConfig { /** * Jenkins服务器ID diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NacosNodeConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NacosNodeExecutorConfig.java similarity index 93% rename from backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NacosNodeConfig.java rename to backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NacosNodeExecutorConfig.java index cf9a06f3..c9462e39 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NacosNodeConfig.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NacosNodeExecutorConfig.java @@ -9,7 +9,7 @@ import java.util.Map; */ @Data @EqualsAndHashCode(callSuper = true) -public class NacosNodeConfig extends NodeConfig { +public class NacosNodeExecutorConfig extends NodeExecutorConfig { /** * Nacos服务器ID diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NodeConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NodeConfig.java deleted file mode 100644 index aeca68b0..00000000 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NodeConfig.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.qqchen.deploy.backend.workflow.engine.executor.node.config; - -import com.fasterxml.jackson.annotation.JsonSubTypes; -import com.fasterxml.jackson.annotation.JsonTypeInfo; -import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; -import lombok.Data; - -/** - * 节点配置基类 - */ -@Data -@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") -@JsonSubTypes({ - @JsonSubTypes.Type(value = ApprovalNodeConfig.class, name = "APPROVAL"), - @JsonSubTypes.Type(value = ScriptNodeConfig.class, name = "SCRIPT"), - @JsonSubTypes.Type(value = ShellNodeConfig.class, name = "SHELL"), - @JsonSubTypes.Type(value = JenkinsNodeConfig.class, name = "JENKINS"), - @JsonSubTypes.Type(value = GitNodeConfig.class, name = "GIT"), - @JsonSubTypes.Type(value = ConditionNodeConfig.class, name = "CONDITION"), - @JsonSubTypes.Type(value = ParallelNodeConfig.class, name = "PARALLEL"), - @JsonSubTypes.Type(value = NacosNodeConfig.class, name = "NACOS"), - @JsonSubTypes.Type(value = HttpNodeConfig.class, name = "HTTP"), - @JsonSubTypes.Type(value = NotifyNodeConfig.class, name = "NOTIFY") -}) -public abstract class NodeConfig { - - /** - * 节点ID - */ - private String id; - - /** - * 节点名称 - */ - private String name; - - /** - * 节点类型 - */ - private NodeTypeEnum type; - - /** - * 超时时间(分钟) - */ - private Integer timeout; - - /** - * 重试次数 - */ - private Integer retryCount; - - /** - * 重试间隔(秒) - */ - private Integer retryInterval; - - /** - * 失败是否继续 - */ - private Boolean continueOnFailed; - - /** - * 描述 - */ - private String description; -} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NodeExecutorConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NodeExecutorConfig.java new file mode 100644 index 00000000..d0f75675 --- /dev/null +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NodeExecutorConfig.java @@ -0,0 +1,48 @@ +package com.qqchen.deploy.backend.workflow.engine.executor.node.config; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; +import lombok.Data; + +/** + * 节点配置基类 + */ +@Data +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") +@JsonIgnoreProperties(ignoreUnknown = true) // 忽略未知字段 +@JsonSubTypes({ + @JsonSubTypes.Type(value = ApprovalNodeExecutorConfig.class, name = "APPROVAL"), + @JsonSubTypes.Type(value = ScriptNodeExecutorConfig.class, name = "SCRIPT"), + @JsonSubTypes.Type(value = ShellNodeExecutorConfig.class, name = "SHELL"), + @JsonSubTypes.Type(value = JenkinsNodeExecutorConfig.class, name = "JENKINS"), + @JsonSubTypes.Type(value = GitNodeExecutorConfig.class, name = "GIT"), + @JsonSubTypes.Type(value = ConditionNodeExecutorConfig.class, name = "CONDITION"), + @JsonSubTypes.Type(value = ParallelNodeExecutorConfig.class, name = "PARALLEL"), + @JsonSubTypes.Type(value = NacosNodeExecutorConfig.class, name = "NACOS"), + @JsonSubTypes.Type(value = HttpNodeExecutorConfig.class, name = "HTTP"), + @JsonSubTypes.Type(value = NotifyNodeExecutorConfig.class, name = "NOTIFY") +}) +public class NodeExecutorConfig { + + /** + * 节点ID + */ + private String id; + + /** + * 节点名称 + */ + private String name; + + /** + * 节点类型 + */ + private NodeTypeEnum type; + + /** + * 描述 + */ + private String description; +} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NotifyNodeConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NotifyNodeExecutorConfig.java similarity index 93% rename from backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NotifyNodeConfig.java rename to backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NotifyNodeExecutorConfig.java index 833335ef..c88336c5 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NotifyNodeConfig.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/NotifyNodeExecutorConfig.java @@ -10,7 +10,7 @@ import java.util.Map; */ @Data @EqualsAndHashCode(callSuper = true) -public class NotifyNodeConfig extends NodeConfig { +public class NotifyNodeExecutorConfig extends NodeExecutorConfig { /** * 通知类型:EMAIL-邮件,SMS-短信,DINGTALK-钉钉,WEIXIN-企业微信 diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ParallelNodeConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ParallelNodeExecutorConfig.java similarity index 92% rename from backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ParallelNodeConfig.java rename to backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ParallelNodeExecutorConfig.java index 92d0b926..2df275ed 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ParallelNodeConfig.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ParallelNodeExecutorConfig.java @@ -9,7 +9,7 @@ import java.util.List; */ @Data @EqualsAndHashCode(callSuper = true) -public class ParallelNodeConfig extends NodeConfig { +public class ParallelNodeExecutorConfig extends NodeExecutorConfig { /** * 并行分支列表 diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ScriptNodeConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ScriptNodeExecutorConfig.java similarity index 81% rename from backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ScriptNodeConfig.java rename to backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ScriptNodeExecutorConfig.java index 1a750008..eb4fbafa 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ScriptNodeConfig.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ScriptNodeExecutorConfig.java @@ -12,7 +12,7 @@ import java.util.Map; */ @Data @EqualsAndHashCode(callSuper = true) -public class ScriptNodeConfig extends NodeConfig { +public class ScriptNodeExecutorConfig extends NodeExecutorConfig { /** * 脚本内容 */ @@ -39,16 +39,6 @@ public class ScriptNodeConfig extends NodeConfig { */ private Integer timeout; - /** - * 环境变量 - */ - private Map environment; - - /** - * 成功退出码 - */ - private Integer successExitCode = 0; - /** * 重试次数 */ @@ -60,15 +50,17 @@ public class ScriptNodeConfig extends NodeConfig { private Integer retryInterval; /** - * 脚本参数 + * 环境变量 */ - private Map arguments; + private Map environment; - public String getScript() { - return script; - } + /** + * 成功退出码 + */ + private Integer successExitCode = 0; - public Map getEnvironment() { - return environment; - } + /** + * 失败是否继续 + */ + private Boolean continueOnFailed; } \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ShellNodeConfig.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ShellNodeExecutorConfig.java similarity index 85% rename from backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ShellNodeConfig.java rename to backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ShellNodeExecutorConfig.java index 53c7a51c..cc56171d 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ShellNodeConfig.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/config/ShellNodeExecutorConfig.java @@ -7,12 +7,12 @@ import java.util.Map; /** * Shell节点配置 - * @deprecated 请使用 {@link ScriptNodeConfig} 替代,设置 language="shell" + * @deprecated 请使用 {@link ScriptNodeExecutorConfig} 替代,设置 language="shell" */ @Deprecated(since = "1.0", forRemoval = true) @Data @EqualsAndHashCode(callSuper = true) -public class ShellNodeConfig extends NodeConfig { +public class ShellNodeExecutorConfig extends NodeExecutorConfig { /** * 执行器类型,固定为 SHELL */ diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/script/command/ScriptCommand.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/script/command/ScriptCommand.java index 3fd608d4..1611cf95 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/script/command/ScriptCommand.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/script/command/ScriptCommand.java @@ -1,6 +1,6 @@ package com.qqchen.deploy.backend.workflow.engine.executor.node.script.command; -import com.qqchen.deploy.backend.workflow.engine.executor.node.config.ScriptNodeConfig; +import com.qqchen.deploy.backend.workflow.engine.executor.node.config.ScriptNodeExecutorConfig; import java.util.List; /** @@ -12,5 +12,5 @@ public interface ScriptCommand { * @param config 脚本配置 * @return 命令行参数列表 */ - List buildCommand(ScriptNodeConfig config); + List buildCommand(ScriptNodeExecutorConfig config); } diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/script/command/impl/PythonScriptCommand.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/script/command/impl/PythonScriptCommand.java index b570bf6b..f8366099 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/script/command/impl/PythonScriptCommand.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/script/command/impl/PythonScriptCommand.java @@ -2,7 +2,7 @@ package com.qqchen.deploy.backend.workflow.engine.executor.node.script.command.i import com.qqchen.deploy.backend.framework.enums.ResponseCode; import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException; -import com.qqchen.deploy.backend.workflow.engine.executor.node.config.ScriptNodeConfig; +import com.qqchen.deploy.backend.workflow.engine.executor.node.config.ScriptNodeExecutorConfig; import com.qqchen.deploy.backend.workflow.engine.executor.node.script.command.ScriptCommand; import com.qqchen.deploy.backend.workflow.engine.executor.node.script.command.ScriptLanguageSupport; import com.qqchen.deploy.backend.workflow.enums.ScriptLanguageEnum; @@ -17,7 +17,7 @@ import java.util.List; @ScriptLanguageSupport(ScriptLanguageEnum.PYTHON) public class PythonScriptCommand implements ScriptCommand { @Override - public List buildCommand(ScriptNodeConfig config) { + public List buildCommand(ScriptNodeExecutorConfig config) { if (config.getInterpreter() == null || config.getInterpreter().trim().isEmpty()) { throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_CONFIG_ERROR, "Python interpreter path must be specified"); diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/script/command/impl/ShellScriptCommand.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/script/command/impl/ShellScriptCommand.java index b2f281ef..b569311f 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/script/command/impl/ShellScriptCommand.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/engine/executor/node/script/command/impl/ShellScriptCommand.java @@ -2,7 +2,7 @@ package com.qqchen.deploy.backend.workflow.engine.executor.node.script.command.i import com.qqchen.deploy.backend.framework.enums.ResponseCode; import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException; -import com.qqchen.deploy.backend.workflow.engine.executor.node.config.ScriptNodeConfig; +import com.qqchen.deploy.backend.workflow.engine.executor.node.config.ScriptNodeExecutorConfig; import com.qqchen.deploy.backend.workflow.engine.executor.node.script.command.ScriptCommand; import com.qqchen.deploy.backend.workflow.engine.executor.node.script.command.ScriptLanguageSupport; import com.qqchen.deploy.backend.workflow.enums.ScriptLanguageEnum; @@ -17,7 +17,7 @@ import java.util.List; @ScriptLanguageSupport(ScriptLanguageEnum.SHELL) public class ShellScriptCommand implements ScriptCommand { @Override - public List buildCommand(ScriptNodeConfig config) { + public List buildCommand(ScriptNodeExecutorConfig config) { if (config.getInterpreter() == null || config.getInterpreter().trim().isEmpty()) { throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_CONFIG_ERROR, "Shell interpreter path must be specified"); diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/NodeInstance.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/NodeInstance.java index 9098a3c0..82e3ea4e 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/NodeInstance.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/NodeInstance.java @@ -1,7 +1,12 @@ package com.qqchen.deploy.backend.workflow.entity; +import com.fasterxml.jackson.databind.ObjectMapper; import com.qqchen.deploy.backend.framework.annotation.LogicDelete; import com.qqchen.deploy.backend.framework.domain.Entity; +import com.qqchen.deploy.backend.framework.enums.ResponseCode; +import com.qqchen.deploy.backend.framework.utils.SpringUtils; +import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException; +import com.qqchen.deploy.backend.workflow.engine.executor.node.config.NodeExecutorConfig; import com.qqchen.deploy.backend.workflow.enums.NodeStatusEnum; import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum; import jakarta.persistence.*; @@ -10,6 +15,9 @@ import lombok.EqualsAndHashCode; import java.time.LocalDateTime; +/** + * + */ @Data @EqualsAndHashCode(callSuper = true) @jakarta.persistence.Entity @@ -18,77 +26,84 @@ import java.time.LocalDateTime; public class NodeInstance extends Entity { /** - * 工作流实例 + * */ @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "workflow_instance_id", nullable = false) private WorkflowInstance workflowInstance; /** - * 节点ID + * ID */ @Column(nullable = false) private String nodeId; /** - * 节点类型 + * */ @Enumerated(EnumType.ORDINAL) @Column(nullable = false) private NodeTypeEnum nodeType; /** - * 节点名称 + * */ @Column(nullable = false) private String name; /** - * 节点状态 + * */ @Enumerated(EnumType.ORDINAL) @Column(nullable = false) private NodeStatusEnum status; /** - * 开始时间 + * */ private LocalDateTime startTime; /** - * 结束时间 + * */ private LocalDateTime endTime; /** - * 节点配置(JSON) + * (JSON) */ @Column(columnDefinition = "TEXT") private String config; /** - * 输入参数(JSON) + * (JSON) */ @Column(columnDefinition = "TEXT") private String input; /** - * 输出结果(JSON) + * (JSON) */ @Column(columnDefinition = "TEXT") private String output; /** - * 错误信息 + * */ @Column(columnDefinition = "TEXT") private String error; /** - * 前置节点ID + * ID */ private String preNodeId; + @Transient + private NodeExecutorConfig configObject; + + private static ObjectMapper getObjectMapper() { + return SpringUtils.getBean(ObjectMapper.class); + } + public String getConfig() { return config; } @@ -96,4 +111,26 @@ public class NodeInstance extends Entity { public String getPreNodeId() { return preNodeId; } -} \ No newline at end of file + + public T getConfigObject(Class configClass) { + if (configObject == null && config != null) { + try { + configObject = getObjectMapper().readValue(this.config, configClass); + } catch (Exception e) { + throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_CONFIG_ERROR, + String.format("Failed to parse config for node %s: %s", name, e.getMessage())); + } + } + return (T) configObject; + } + + public void setConfigObject(NodeExecutorConfig config) { + this.configObject = config; + try { + this.config = getObjectMapper().writeValueAsString(config); + } catch (Exception e) { + throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_CONFIG_ERROR, + String.format("Failed to serialize config for node %s: %s", name, e.getMessage())); + } + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowInstance.java b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowInstance.java index 34a5afc9..198f0a30 100644 --- a/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowInstance.java +++ b/backend/src/main/java/com/qqchen/deploy/backend/workflow/entity/WorkflowInstance.java @@ -161,16 +161,6 @@ public class WorkflowInstance extends Entity { this.error = reason; } - /** - * 完成工作流实例 - */ - public void complete() { - if (!canComplete()) { - throw new IllegalStateException("Cannot complete workflow instance in " + status + " status"); - } - this.status = WorkflowInstanceStatusEnum.COMPLETED; - this.endTime = LocalDateTime.now(); - } /** * 标记工作流实例为失败