可正常启动,工作流可以正常运行,增加了其他节点,但是还没运行过,编译无错。

This commit is contained in:
戚辰先生 2024-12-08 17:29:04 +08:00
parent 6a9b0f36b0
commit ed0309f45c
43 changed files with 384 additions and 296 deletions

View File

@ -2,7 +2,7 @@ package com.qqchen.deploy.backend.workflow.dto;
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
import com.qqchen.deploy.backend.workflow.engine.definition.TaskExecutorDefinition;
import com.qqchen.deploy.backend.workflow.enums.NodeCategory;
import com.qqchen.deploy.backend.workflow.enums.NodeCategoryEnum;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
@ -39,7 +39,7 @@ public class NodeTypeDTO extends BaseDTO {
* 节点类型分类
*/
@NotNull(message = "节点类型分类不能为空")
private NodeCategory category;
private NodeCategoryEnum category;
/**
* 节点图标

View File

@ -3,7 +3,7 @@ package com.qqchen.deploy.backend.workflow.dto.query;
import com.qqchen.deploy.backend.framework.annotation.QueryField;
import com.qqchen.deploy.backend.framework.enums.QueryType;
import com.qqchen.deploy.backend.framework.query.BaseQuery;
import com.qqchen.deploy.backend.workflow.enums.NodeCategory;
import com.qqchen.deploy.backend.workflow.enums.NodeCategoryEnum;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -30,5 +30,5 @@ public class NodeTypeQuery extends BaseQuery {
* 节点类型分类
*/
@QueryField(field = "category")
private NodeCategory category;
private NodeCategoryEnum category;
}

View File

@ -6,7 +6,7 @@ import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.workflow.engine.context.DefaultWorkflowContext;
import com.qqchen.deploy.backend.workflow.engine.context.WorkflowContextOperations;
import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException;
import com.qqchen.deploy.backend.workflow.engine.executor.NodeExecutor;
import com.qqchen.deploy.backend.workflow.engine.executor.node.NodeExecutor;
import com.qqchen.deploy.backend.workflow.engine.parser.WorkflowDefinitionParser;
import com.qqchen.deploy.backend.workflow.entity.NodeConfig;
import com.qqchen.deploy.backend.workflow.entity.NodeInstance;
@ -27,8 +27,6 @@ import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

View File

@ -1,6 +1,6 @@
package com.qqchen.deploy.backend.workflow.engine.config;
import com.qqchen.deploy.backend.workflow.engine.executor.NodeExecutor;
import com.qqchen.deploy.backend.workflow.engine.executor.node.NodeExecutor;
import com.qqchen.deploy.backend.workflow.engine.executor.task.TaskExecutor;
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum;
import org.springframework.context.annotation.Bean;

View File

@ -1,22 +0,0 @@
package com.qqchen.deploy.backend.workflow.engine.executor;
import lombok.Data;
@Data
public class GatewayCondition {
/**
* 条件表达式(SpEL表达式)
*/
private String expression;
/**
* 下一个节点ID
*/
private String nextNodeId;
/**
* 条件描述
*/
private String description;
}

View File

@ -1,38 +0,0 @@
package com.qqchen.deploy.backend.workflow.engine.executor;
import lombok.Data;
import java.util.List;
@Data
public class GatewayConfig {
/**
* 网关类型
*/
private GatewayType type;
/**
* 网关名称
*/
private String name;
/**
* 网关描述
*/
private String description;
/**
* 条件列表(排他网关和包容网关使用)
*/
private List<GatewayCondition> conditions;
/**
* 默认节点ID(排他网关使用)
*/
private String defaultNodeId;
/**
* 并行节点ID列表(并行网关使用)
*/
private List<String> parallelNodeIds;
}

View File

@ -1,158 +0,0 @@
package com.qqchen.deploy.backend.workflow.engine.executor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.workflow.engine.context.WorkflowContextOperations;
import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException;
import com.qqchen.deploy.backend.workflow.entity.NodeInstance;
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Component
public class GatewayNodeExecutor implements NodeExecutor {
private final ObjectMapper objectMapper = new ObjectMapper();
private final ExpressionParser expressionParser = new SpelExpressionParser();
@Override
public NodeTypeEnum getNodeType() {
return NodeTypeEnum.GATEWAY;
}
@Override
public void execute(NodeInstance nodeInstance, WorkflowContextOperations context) {
try {
GatewayConfig config = objectMapper.readValue(nodeInstance.getConfig(), GatewayConfig.class);
if (config.getType() == null) {
throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_CONFIG_ERROR);
}
switch (config.getType()) {
case PARALLEL:
handleParallelGateway(nodeInstance, context, config);
break;
case EXCLUSIVE:
handleExclusiveGateway(nodeInstance, context, config);
break;
case INCLUSIVE:
handleInclusiveGateway(nodeInstance, context, config);
break;
default:
throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_CONFIG_ERROR);
}
} catch (Exception e) {
throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_EXECUTION_FAILED, e);
}
}
private void handleExclusiveGateway(NodeInstance nodeInstance, WorkflowContextOperations context, GatewayConfig config) {
try {
for (GatewayCondition condition : config.getConditions()) {
if (evaluateCondition(condition.getExpression(), context)) {
nodeInstance.setOutput(objectMapper.createObjectNode()
.put("nextNodeId", condition.getNextNodeId())
.toString());
return;
}
}
throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_EXECUTION_FAILED);
} catch (Exception e) {
throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_EXECUTION_FAILED, e);
}
}
private void handleParallelGateway(NodeInstance nodeInstance, WorkflowContextOperations context, GatewayConfig config) {
try {
List<String> nextNodeIds = new ArrayList<>();
for (GatewayCondition condition : config.getConditions()) {
nextNodeIds.add(condition.getNextNodeId());
}
nodeInstance.setOutput(objectMapper.createObjectNode()
.put("nextNodeIds", String.join(",", nextNodeIds))
.toString());
} catch (Exception e) {
throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_EXECUTION_FAILED, e);
}
}
private void handleInclusiveGateway(NodeInstance nodeInstance, WorkflowContextOperations context, GatewayConfig config) {
try {
List<String> nextNodeIds = new ArrayList<>();
for (GatewayCondition condition : config.getConditions()) {
if (evaluateCondition(condition.getExpression(), context)) {
nextNodeIds.add(condition.getNextNodeId());
}
}
if (nextNodeIds.isEmpty()) {
throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_EXECUTION_FAILED);
}
nodeInstance.setOutput(objectMapper.createObjectNode()
.put("nextNodeIds", String.join(",", nextNodeIds))
.toString());
} catch (Exception e) {
throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_EXECUTION_FAILED, e);
}
}
private boolean evaluateCondition(String expression, WorkflowContextOperations context) {
try {
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
evaluationContext.setVariables(context.getVariables());
Expression exp = expressionParser.parseExpression(expression);
return exp.getValue(evaluationContext, Boolean.class);
} catch (Exception e) {
throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_EXECUTION_FAILED, e);
}
}
@Override
public void validate(String config) {
try {
GatewayConfig gatewayConfig = objectMapper.readValue(config, GatewayConfig.class);
if (gatewayConfig.getType() == null) {
throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_CONFIG_ERROR);
}
// 验证条件表达式
if (gatewayConfig.getConditions() != null) {
for (GatewayCondition condition : gatewayConfig.getConditions()) {
try {
expressionParser.parseExpression(condition.getExpression());
} catch (Exception e) {
throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_CONFIG_ERROR);
}
}
}
} catch (Exception e) {
throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_CONFIG_ERROR);
}
}
@Override
public void terminate(NodeInstance nodeInstance, WorkflowContextOperations context) {
// Gateway nodes are instant operations, no need to terminate
}
@Data
public static class GatewayConfig {
private GatewayType type; // 网关类型PARALLEL, EXCLUSIVE, INCLUSIVE
private List<GatewayCondition> conditions; // 网关条件
}
@Data
public static class GatewayCondition {
private String expression; // 条件表达式
private String nextNodeId; // 下一个节点ID
}
}

View File

@ -0,0 +1,35 @@
package com.qqchen.deploy.backend.workflow.engine.executor.gateway;
import lombok.Data;
/**
* 分支汇聚配置
*/
@Data
public class BranchConvergeConfig {
/**
* 汇聚策略
*/
private ConvergeStrategy strategy;
/**
* 需要完成的分支数量N个完成时使用
*/
private Integer requiredCount;
public enum ConvergeStrategy {
ALL("全部完成"),
ANY("任一完成"),
N("N个完成");
private final String description;
ConvergeStrategy(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
}

View File

@ -0,0 +1,46 @@
package com.qqchen.deploy.backend.workflow.engine.executor.gateway;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
* 基于条件的网关配置基类
*/
@Data
@EqualsAndHashCode(callSuper = true)
public abstract class ConditionalGatewayConfig extends GatewayConfig {
/**
* 条件分支列表
*/
private List<ConditionalBranch> branches;
/**
* 默认分支节点ID
*/
private String defaultNodeId;
@Data
public static class ConditionalBranch {
/**
* 分支名称
*/
private String name;
/**
* 条件表达式
*/
private String condition;
/**
* 目标节点ID
*/
private String targetNodeId;
/**
* 分支描述
*/
private String description;
}
}

View File

@ -0,0 +1,41 @@
package com.qqchen.deploy.backend.workflow.engine.executor.gateway;
import com.qqchen.deploy.backend.workflow.engine.context.WorkflowContextOperations;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import java.util.Collections;
import java.util.List;
/**
* 排他网关配置
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class ExclusiveGatewayConfig extends ConditionalGatewayConfig {
private final ExpressionParser expressionParser = new SpelExpressionParser();
@Override
public List<String> getNextNodeIds(WorkflowContextOperations context) {
// 返回第一个满足条件的分支的targetNodeId
for (ConditionalBranch branch : getBranches()) {
if (evaluateCondition(branch.getCondition(), context)) {
return Collections.singletonList(branch.getTargetNodeId());
}
}
return Collections.singletonList(getDefaultNodeId());
}
private boolean evaluateCondition(String condition, WorkflowContextOperations context) {
try {
StandardEvaluationContext evaluationContext = new StandardEvaluationContext(context);
return Boolean.TRUE.equals(expressionParser.parseExpression(condition)
.getValue(evaluationContext, Boolean.class));
} catch (Exception e) {
return false;
}
}
}

View File

@ -0,0 +1,41 @@
package com.qqchen.deploy.backend.workflow.engine.executor.gateway;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.qqchen.deploy.backend.workflow.engine.context.WorkflowContextOperations;
import com.qqchen.deploy.backend.workflow.enums.GatewayTypeEnum;
import lombok.Data;
import java.util.List;
/**
* 网关配置基类
*/
@Data
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = ExclusiveGatewayConfig.class, name = "EXCLUSIVE"),
@JsonSubTypes.Type(value = ParallelGatewayConfig.class, name = "PARALLEL"),
@JsonSubTypes.Type(value = InclusiveGatewayConfig.class, name = "INCLUSIVE")
})
public abstract class GatewayConfig {
/**
* 网关类型
*/
private GatewayTypeEnum type;
/**
* 网关名称
*/
private String name;
/**
* 网关描述
*/
private String description;
/**
* 获取下一个节点IDs
*/
public abstract List<String> getNextNodeIds(WorkflowContextOperations context);
}

View File

@ -0,0 +1,59 @@
package com.qqchen.deploy.backend.workflow.engine.executor.gateway;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.workflow.engine.context.WorkflowContextOperations;
import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException;
import com.qqchen.deploy.backend.workflow.engine.executor.node.NodeExecutor;
import com.qqchen.deploy.backend.workflow.entity.NodeInstance;
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.List;
@Slf4j
@Component
public class GatewayNodeExecutor implements NodeExecutor {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public NodeTypeEnum getNodeType() {
return NodeTypeEnum.GATEWAY;
}
@Override
public void execute(NodeInstance nodeInstance, WorkflowContextOperations context) {
try {
// 解析网关配置
GatewayConfig config = objectMapper.readValue(nodeInstance.getConfig(), GatewayConfig.class);
// 获取下一个节点IDs
List<String> nextNodeIds = config.getNextNodeIds(context);
// 设置输出
nodeInstance.setOutput(objectMapper.createObjectNode()
.put("nextNodeIds", String.join(",", nextNodeIds))
.toString());
} catch (Exception e) {
log.error("Gateway node execution failed", e);
throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_EXECUTION_FAILED, e);
}
}
@Override
public void validate(String config) {
try {
objectMapper.readValue(config, GatewayConfig.class);
} catch (Exception e) {
throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_CONFIG_ERROR);
}
}
@Override
public void terminate(NodeInstance nodeInstance, WorkflowContextOperations context) {
// Gateway nodes are instant operations, no need to terminate
}
}

View File

@ -0,0 +1,51 @@
package com.qqchen.deploy.backend.workflow.engine.executor.gateway;
import com.qqchen.deploy.backend.workflow.engine.context.WorkflowContextOperations;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import java.util.List;
import java.util.stream.Collectors;
/**
* 包容网关配置
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class InclusiveGatewayConfig extends ConditionalGatewayConfig {
/**
* 汇聚配置
*/
private BranchConvergeConfig convergeConfig;
private final ExpressionParser expressionParser = new SpelExpressionParser();
@Override
public List<String> getNextNodeIds(WorkflowContextOperations context) {
// 返回所有满足条件的分支的targetNodeId
List<String> nextNodeIds = getBranches().stream()
.filter(branch -> evaluateCondition(branch.getCondition(), context))
.map(ConditionalBranch::getTargetNodeId)
.collect(Collectors.toList());
// 如果没有满足条件的分支使用默认分支
if (nextNodeIds.isEmpty() && getDefaultNodeId() != null) {
nextNodeIds.add(getDefaultNodeId());
}
return nextNodeIds;
}
private boolean evaluateCondition(String condition, WorkflowContextOperations context) {
try {
StandardEvaluationContext evaluationContext = new StandardEvaluationContext(context);
return Boolean.TRUE.equals(expressionParser.parseExpression(condition)
.getValue(evaluationContext, Boolean.class));
} catch (Exception e) {
return false;
}
}
}

View File

@ -0,0 +1,51 @@
package com.qqchen.deploy.backend.workflow.engine.executor.gateway;
import com.qqchen.deploy.backend.workflow.engine.context.WorkflowContextOperations;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
import java.util.stream.Collectors;
/**
* 并行网关配置
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class ParallelGatewayConfig extends GatewayConfig {
/**
* 并行分支列表
*/
private List<ParallelBranch> branches;
/**
* 汇聚配置
*/
private BranchConvergeConfig convergeConfig;
@Data
public static class ParallelBranch {
/**
* 分支名称
*/
private String name;
/**
* 目标节点ID
*/
private String targetNodeId;
/**
* 分支描述
*/
private String description;
}
@Override
public List<String> getNextNodeIds(WorkflowContextOperations context) {
// 返回所有分支的targetNodeId
return branches.stream()
.map(ParallelBranch::getTargetNodeId)
.collect(Collectors.toList());
}
}

View File

@ -1,10 +1,9 @@
package com.qqchen.deploy.backend.workflow.engine.node;
package com.qqchen.deploy.backend.workflow.engine.executor.node;
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.system.enums.LogLevelEnum;
import com.qqchen.deploy.backend.workflow.engine.context.WorkflowContextOperations;
import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException;
import com.qqchen.deploy.backend.workflow.engine.executor.NodeExecutor;
import com.qqchen.deploy.backend.workflow.entity.NodeInstance;
import com.qqchen.deploy.backend.workflow.enums.NodeStatusEnum;
import com.qqchen.deploy.backend.workflow.repository.INodeInstanceRepository;

View File

@ -1,8 +1,7 @@
package com.qqchen.deploy.backend.workflow.engine.node.executor;
package com.qqchen.deploy.backend.workflow.engine.executor.node;
import com.qqchen.deploy.backend.system.enums.LogLevelEnum;
import com.qqchen.deploy.backend.workflow.engine.context.WorkflowContextOperations;
import com.qqchen.deploy.backend.workflow.engine.node.AbstractNodeExecutor;
import com.qqchen.deploy.backend.workflow.entity.NodeInstance;
import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance;
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum;

View File

@ -1,4 +1,4 @@
package com.qqchen.deploy.backend.workflow.engine.executor;
package com.qqchen.deploy.backend.workflow.engine.executor.node;
import com.qqchen.deploy.backend.workflow.engine.context.WorkflowContextOperations;
import com.qqchen.deploy.backend.workflow.entity.NodeInstance;

View File

@ -1,12 +1,11 @@
package com.qqchen.deploy.backend.workflow.engine.node.executor;
package com.qqchen.deploy.backend.workflow.engine.executor.node;
import com.fasterxml.jackson.databind.ObjectMapper;
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.node.AbstractNodeExecutor;
import com.qqchen.deploy.backend.workflow.engine.node.ScriptNodeConfig;
import com.qqchen.deploy.backend.workflow.engine.executor.node.config.ScriptNodeConfig;
import com.qqchen.deploy.backend.workflow.entity.NodeInstance;
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum;
import com.qqchen.deploy.backend.workflow.service.WorkflowVariableOperations;

View File

@ -1,12 +1,11 @@
package com.qqchen.deploy.backend.workflow.engine.node.executor;
package com.qqchen.deploy.backend.workflow.engine.executor.node;
import com.fasterxml.jackson.databind.ObjectMapper;
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.node.AbstractNodeExecutor;
import com.qqchen.deploy.backend.workflow.engine.node.ShellNodeConfig;
import com.qqchen.deploy.backend.workflow.engine.executor.node.config.ShellNodeConfig;
import com.qqchen.deploy.backend.workflow.entity.NodeInstance;
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum;
import com.qqchen.deploy.backend.workflow.service.WorkflowVariableOperations;

View File

@ -1,8 +1,7 @@
package com.qqchen.deploy.backend.workflow.engine.node.executor;
package com.qqchen.deploy.backend.workflow.engine.executor.node;
import com.qqchen.deploy.backend.system.enums.LogLevelEnum;
import com.qqchen.deploy.backend.workflow.engine.context.WorkflowContextOperations;
import com.qqchen.deploy.backend.workflow.engine.node.AbstractNodeExecutor;
import com.qqchen.deploy.backend.workflow.entity.NodeInstance;
import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance;
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum;

View File

@ -1,10 +1,11 @@
package com.qqchen.deploy.backend.workflow.engine.executor;
package com.qqchen.deploy.backend.workflow.engine.executor.node;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qqchen.deploy.backend.system.enums.LogLevelEnum;
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.workflow.engine.context.WorkflowContextOperations;
import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException;
import com.qqchen.deploy.backend.workflow.engine.executor.task.TaskConfig;
import com.qqchen.deploy.backend.workflow.entity.NodeInstance;
import com.qqchen.deploy.backend.workflow.enums.NodeStatusEnum;
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum;

View File

@ -1,4 +1,4 @@
package com.qqchen.deploy.backend.workflow.engine.node;
package com.qqchen.deploy.backend.workflow.engine.executor.node.config;
import lombok.Data;
import lombok.EqualsAndHashCode;

View File

@ -1,4 +1,4 @@
package com.qqchen.deploy.backend.workflow.engine.node;
package com.qqchen.deploy.backend.workflow.engine.executor.node.config;
import lombok.Data;
import lombok.EqualsAndHashCode;

View File

@ -1,4 +1,4 @@
package com.qqchen.deploy.backend.workflow.engine.node;
package com.qqchen.deploy.backend.workflow.engine.executor.node.config;
import lombok.Data;
import lombok.EqualsAndHashCode;

View File

@ -1,4 +1,4 @@
package com.qqchen.deploy.backend.workflow.engine.node;
package com.qqchen.deploy.backend.workflow.engine.executor.node.config;
import lombok.Data;
import lombok.EqualsAndHashCode;

View File

@ -1,4 +1,4 @@
package com.qqchen.deploy.backend.workflow.engine.node;
package com.qqchen.deploy.backend.workflow.engine.executor.node.config;
import lombok.Data;
import lombok.EqualsAndHashCode;

View File

@ -1,4 +1,4 @@
package com.qqchen.deploy.backend.workflow.engine.node;
package com.qqchen.deploy.backend.workflow.engine.executor.node.config;
import lombok.Data;
import lombok.EqualsAndHashCode;

View File

@ -1,7 +1,8 @@
package com.qqchen.deploy.backend.workflow.engine.node;
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;
/**
@ -36,7 +37,7 @@ public abstract class NodeConfig {
/**
* 节点类型
*/
private NodeType type;
private NodeTypeEnum type;
/**
* 超时时间分钟

View File

@ -1,4 +1,4 @@
package com.qqchen.deploy.backend.workflow.engine.node;
package com.qqchen.deploy.backend.workflow.engine.executor.node.config;
import lombok.Data;
import lombok.EqualsAndHashCode;

View File

@ -1,4 +1,4 @@
package com.qqchen.deploy.backend.workflow.engine.node;
package com.qqchen.deploy.backend.workflow.engine.executor.node.config;
import lombok.Data;
import lombok.EqualsAndHashCode;

View File

@ -1,4 +1,4 @@
package com.qqchen.deploy.backend.workflow.engine.node;
package com.qqchen.deploy.backend.workflow.engine.executor.node.config;
import lombok.Data;
import lombok.EqualsAndHashCode;

View File

@ -1,4 +1,4 @@
package com.qqchen.deploy.backend.workflow.engine.node;
package com.qqchen.deploy.backend.workflow.engine.executor.node.config;
import lombok.Data;
import lombok.EqualsAndHashCode;

View File

@ -1,5 +1,6 @@
package com.qqchen.deploy.backend.workflow.engine.executor;
package com.qqchen.deploy.backend.workflow.engine.executor.task;
import com.qqchen.deploy.backend.workflow.enums.TaskTypeEnum;
import lombok.Data;
import java.util.Map;
@ -10,7 +11,7 @@ public class TaskConfig {
/**
* 任务类型
*/
private TaskType type;
private TaskTypeEnum type;
/**
* 任务名称

View File

@ -1,27 +0,0 @@
package com.qqchen.deploy.backend.workflow.engine.node;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 节点类型枚举
*/
@Getter
@AllArgsConstructor
public enum NodeType {
START("START", "开始节点"),
END("END", "结束节点"),
APPROVAL("APPROVAL", "审批节点"),
SCRIPT("SCRIPT", "脚本节点"),
JENKINS("JENKINS", "Jenkins构建节点"),
GIT("GIT", "Git操作节点"),
CONDITION("CONDITION", "条件节点"),
PARALLEL("PARALLEL", "并行节点"),
NACOS("NACOS", "Nacos配置节点"),
HTTP("HTTP", "HTTP请求节点"),
NOTIFY("NOTIFY", "通知节点");
private final String code;
private final String description;
}

View File

@ -2,7 +2,7 @@ package com.qqchen.deploy.backend.workflow.entity;
import com.qqchen.deploy.backend.framework.annotation.LogicDelete;
import com.qqchen.deploy.backend.framework.domain.Entity;
import com.qqchen.deploy.backend.workflow.enums.NodeCategory;
import com.qqchen.deploy.backend.workflow.enums.NodeCategoryEnum;
import jakarta.persistence.Column;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
@ -43,7 +43,7 @@ public class NodeType extends Entity<Long> {
*/
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private NodeCategory category;
private NodeCategoryEnum category;
/**
* 节点图标

View File

@ -1,11 +1,11 @@
package com.qqchen.deploy.backend.workflow.engine.executor;
package com.qqchen.deploy.backend.workflow.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum GatewayType {
public enum GatewayTypeEnum {
EXCLUSIVE("EXCLUSIVE", "排他网关"),
PARALLEL("PARALLEL", "并行网关"),

View File

@ -6,7 +6,7 @@ import lombok.Getter;
* 节点分类枚举
*/
@Getter
public enum NodeCategory {
public enum NodeCategoryEnum {
/**
* 基础节点如开始结束节点
*/
@ -32,7 +32,7 @@ public enum NodeCategory {
*/
private final String name;
NodeCategory(String name) {
NodeCategoryEnum(String name) {
this.name = name;
}
}

View File

@ -19,7 +19,12 @@ public enum NodeTypeEnum {
SCRIPT(6, "SCRIPT", "脚本节点"),
APPROVAL(7, "APPROVAL", "审批节点"),
JENKINS(8, "JENKINS", "Jenkins任务节点"),
GIT(9, "GIT", "Git操作节点");
GIT(9, "GIT", "Git操作节点"),
CONDITION(10, "CONDITION", "条件节点"),
PARALLEL(11, "PARALLEL", "并行节点"),
NACOS(12, "NACOS", "Nacos配置节点"),
HTTP(13, "HTTP", "HTTP请求节点"),
NOTIFY(14, "NOTIFY", "通知节点");
private final int value;
private final String code;

View File

@ -1,11 +1,11 @@
package com.qqchen.deploy.backend.workflow.engine.executor;
package com.qqchen.deploy.backend.workflow.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum TaskType {
public enum TaskTypeEnum {
HTTP("HTTP", "HTTP请求"),
JAVA("JAVA", "Java方法");

View File

@ -4,6 +4,7 @@ import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance;
import com.qqchen.deploy.backend.workflow.entity.WorkflowVariable;
import com.qqchen.deploy.backend.workflow.enums.VariableScopeEnum;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
@ -79,10 +80,18 @@ public interface IWorkflowVariableRepository extends IBaseRepository<WorkflowVar
@Param("scope") VariableScopeEnum scope);
/**
* 根据工作流实例ID删除所有变量软删除
* 删除工作流实例变量
*
* @param workflowInstanceId 工作流实例ID
*/
@Modifying
@Query("DELETE FROM WorkflowVariable v WHERE v.workflowInstance.id = :workflowInstanceId")
void deleteWorkflowInstanceVariable(@Param("workflowInstanceId") Long workflowInstanceId);
/**
* 删除工作流实例的所有变量逻辑删除
*/
@Modifying
@Query("UPDATE WorkflowVariable v SET v.deleted = true, v.updateTime = CURRENT_TIMESTAMP WHERE v.workflowInstance.id = :workflowInstanceId AND v.deleted = false")
void deleteByWorkflowInstanceId(@Param("workflowInstanceId") Long workflowInstanceId);
}

View File

@ -8,7 +8,7 @@ import com.qqchen.deploy.backend.workflow.converter.NodeTypeConverter;
import com.qqchen.deploy.backend.workflow.dto.NodeTypeDTO;
import com.qqchen.deploy.backend.workflow.engine.definition.TaskExecutorDefinition;
import com.qqchen.deploy.backend.workflow.entity.NodeType;
import com.qqchen.deploy.backend.workflow.enums.NodeCategory;
import com.qqchen.deploy.backend.workflow.enums.NodeCategoryEnum;
import com.qqchen.deploy.backend.workflow.repository.INodeTypeRepository;
import com.qqchen.deploy.backend.workflow.service.INodeTypeService;
import jakarta.annotation.Resource;
@ -47,7 +47,7 @@ public class NodeTypeServiceImpl extends BaseServiceImpl<NodeType, NodeTypeDTO,
.orElseThrow(() -> new BusinessException(ResponseCode.WORKFLOW_NODE_TYPE_NOT_FOUND));
// 2. 检查节点类型是否为任务节点
if (!NodeCategory.TASK.equals(nodeType.getCategory())) {
if (!NodeCategoryEnum.TASK.equals(nodeType.getCategory())) {
// 非任务节点没有执行器列表
return Collections.emptyList();
}

View File

@ -4,7 +4,7 @@ import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.workflow.engine.context.DefaultWorkflowContext;
import com.qqchen.deploy.backend.workflow.engine.context.WorkflowContext;
import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException;
import com.qqchen.deploy.backend.workflow.engine.executor.NodeExecutor;
import com.qqchen.deploy.backend.workflow.engine.executor.node.NodeExecutor;
import com.qqchen.deploy.backend.workflow.entity.NodeInstance;
import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition;
import com.qqchen.deploy.backend.workflow.entity.WorkflowInstance;
@ -21,9 +21,7 @@ import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

View File

@ -2,6 +2,7 @@ package com.qqchen.deploy.backend.workflow.engine.executor;
import com.qqchen.deploy.backend.system.enums.LogLevelEnum;
import com.qqchen.deploy.backend.workflow.engine.context.WorkflowContext;
import com.qqchen.deploy.backend.workflow.engine.executor.node.StartNodeExecutor;
import com.qqchen.deploy.backend.workflow.entity.NodeInstance;
import com.qqchen.deploy.backend.workflow.enums.NodeStatusEnum;
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum;