feat: 2.6.0
1. 完成新增接口
This commit is contained in:
parent
a70f941ad3
commit
bff0bd9b1d
@ -468,6 +468,7 @@ CREATE TABLE `workflow_node`
|
|||||||
`namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
|
`namespace_id` varchar(64) NOT NULL DEFAULT '764d604ec6fc45f68cd92514c40e9e1a' COMMENT '命名空间id',
|
||||||
`group_name` varchar(64) NOT NULL COMMENT '组名称',
|
`group_name` varchar(64) NOT NULL COMMENT '组名称',
|
||||||
`job_id` bigint(20) NOT NULL COMMENT '任务信息id',
|
`job_id` bigint(20) NOT NULL COMMENT '任务信息id',
|
||||||
|
`workflow_id` bigint(20) NOT NULL COMMENT '工作流ID',
|
||||||
`node_type` tinyint(4) NOT NULL DEFAULT 1 COMMENT '1、任务节点 2、条件节点',
|
`node_type` tinyint(4) NOT NULL DEFAULT 1 COMMENT '1、任务节点 2、条件节点',
|
||||||
`expression_type` tinyint(4) NOT NULL DEFAULT 0 COMMENT '1、SpEl、2、Aviator 3、QL',
|
`expression_type` tinyint(4) NOT NULL DEFAULT 0 COMMENT '1、SpEl、2、Aviator 3、QL',
|
||||||
`fail_strategy` tinyint(4) NOT NULL DEFAULT 0 COMMENT '失败策略 1、跳过 2、阻塞',
|
`fail_strategy` tinyint(4) NOT NULL DEFAULT 0 COMMENT '失败策略 1、跳过 2、阻塞',
|
||||||
|
@ -8,6 +8,9 @@ import java.time.LocalDateTime;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* 工作流
|
* 工作流
|
||||||
@ -40,10 +43,25 @@ public class Workflow implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private String groupName;
|
private String groupName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发类型
|
||||||
|
*/
|
||||||
|
private Integer triggerType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发间隔
|
||||||
|
*/
|
||||||
|
private String triggerInterval;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行超时时间
|
||||||
|
*/
|
||||||
|
private Integer executorTimeout;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 工作流状态 0、关闭、1、开启
|
* 工作流状态 0、关闭、1、开启
|
||||||
*/
|
*/
|
||||||
private Byte workflowStatus;
|
private Integer workflowStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务执行时间
|
* 任务执行时间
|
||||||
|
@ -44,6 +44,11 @@ public class WorkflowNode implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private Long jobId;
|
private Long jobId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作流ID
|
||||||
|
*/
|
||||||
|
private Long workflowId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 1、任务节点 2、条件节点
|
* 1、任务节点 2、条件节点
|
||||||
*/
|
*/
|
||||||
|
@ -4,6 +4,7 @@ import com.aizuda.easy.retry.server.web.model.request.WorkflowRequestVO;
|
|||||||
import com.aizuda.easy.retry.server.web.service.WorkflowService;
|
import com.aizuda.easy.retry.server.web.service.WorkflowService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -18,9 +19,8 @@ public class WorkflowController {
|
|||||||
|
|
||||||
private final WorkflowService workflowService;
|
private final WorkflowService workflowService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public Boolean saveWorkflow(@RequestBody WorkflowRequestVO workflowRequestVO) {
|
public Boolean saveWorkflow(@RequestBody @Validated WorkflowRequestVO workflowRequestVO) {
|
||||||
return workflowService.saveWorkflow(workflowRequestVO);
|
return workflowService.saveWorkflow(workflowRequestVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ public class WorkflowRequestVO {
|
|||||||
@Pattern(regexp = "^[A-Za-z0-9_]{1,64}$", message = "仅支持长度为1~64字符且类型为数字、字母和下划线")
|
@Pattern(regexp = "^[A-Za-z0-9_]{1,64}$", message = "仅支持长度为1~64字符且类型为数字、字母和下划线")
|
||||||
private String groupName;
|
private String groupName;
|
||||||
|
|
||||||
@NotBlank(message = "触发类型不能为空")
|
@NotNull(message = "触发类型不能为空")
|
||||||
private Integer triggerType;
|
private Integer triggerType;
|
||||||
|
|
||||||
@NotBlank(message = "触发间隔不能为空")
|
@NotBlank(message = "触发间隔不能为空")
|
||||||
@ -30,34 +30,62 @@ public class WorkflowRequestVO {
|
|||||||
@NotNull(message = "执行超时时间不能为空")
|
@NotNull(message = "执行超时时间不能为空")
|
||||||
private Integer executorTimeout;
|
private Integer executorTimeout;
|
||||||
|
|
||||||
@NotEmpty(message = "执行超时时间不能为空")
|
/**
|
||||||
@Valid
|
* 0、关闭、1、开启
|
||||||
|
*/
|
||||||
|
@NotNull(message = "工作流状态")
|
||||||
|
private Integer workflowStatus;
|
||||||
|
|
||||||
|
@NotEmpty(message = "节点信息不能为空")
|
||||||
private List<NodeInfo> nodeInfos;
|
private List<NodeInfo> nodeInfos;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class NodeInfo {
|
public static class NodeInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 优先级
|
||||||
|
*/
|
||||||
|
private Integer priorityLevel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1、任务节点 2、条件节点
|
||||||
|
*/
|
||||||
|
@NotNull(message = "节点类型不能为空 ")
|
||||||
|
private Integer nodeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务ID
|
||||||
|
*/
|
||||||
|
@NotNull(message = "任务ID不能为空")
|
||||||
|
private Long jobId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表达式类型 1、SpEl、2、Aviator 3、QL
|
||||||
|
*/
|
||||||
|
@NotNull(message = "表达式类型不能为空")
|
||||||
|
private Integer expressionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 条件节点表达式
|
* 条件节点表达式
|
||||||
*/
|
*/
|
||||||
private String nodeExpression;
|
private String nodeExpression;
|
||||||
|
|
||||||
@NotNull(message = "节点类型不能为空")
|
/**
|
||||||
private Integer nodeType;
|
* 1、跳过 2、阻塞
|
||||||
|
*/
|
||||||
@NotNull(message = "任务ID不能为空")
|
|
||||||
private Long jobId;
|
|
||||||
|
|
||||||
@NotNull(message = "表达式类型不能为空")
|
|
||||||
private Integer expressionType;
|
|
||||||
|
|
||||||
@NotNull(message = "失败策略不能为空")
|
@NotNull(message = "失败策略不能为空")
|
||||||
private Integer failStrategy;
|
private Integer failStrategy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工作流状态 0、关闭、1、开启
|
||||||
|
*/
|
||||||
|
@NotNull(message = "工作流状态不能为空")
|
||||||
|
private Integer workflowNodeStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 子节点
|
* 子节点
|
||||||
*/
|
*/
|
||||||
private List<NodeInfo> childrenList;
|
private List<NodeInfo> childreList;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.aizuda.easy.retry.server.web.service.convert;
|
||||||
|
|
||||||
|
import com.aizuda.easy.retry.server.web.model.request.WorkflowRequestVO;
|
||||||
|
import com.aizuda.easy.retry.template.datasource.persistence.po.Workflow;
|
||||||
|
import com.aizuda.easy.retry.template.datasource.persistence.po.WorkflowNode;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: xiaowoniu
|
||||||
|
* @date : 2023-12-13
|
||||||
|
* @since : 2.5.0
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface WorkflowConverter {
|
||||||
|
|
||||||
|
WorkflowConverter INSTANCE = Mappers.getMapper(WorkflowConverter.class);
|
||||||
|
|
||||||
|
Workflow toWorkflow(WorkflowRequestVO workflowRequestVO);
|
||||||
|
|
||||||
|
WorkflowNode toWorkflowNode(WorkflowRequestVO.NodeInfo nodeInfo);
|
||||||
|
|
||||||
|
}
|
@ -1,8 +1,28 @@
|
|||||||
package com.aizuda.easy.retry.server.web.service.impl;
|
package com.aizuda.easy.retry.server.web.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.aizuda.easy.retry.common.core.util.JsonUtil;
|
||||||
|
import com.aizuda.easy.retry.server.common.exception.EasyRetryServerException;
|
||||||
import com.aizuda.easy.retry.server.web.model.request.WorkflowRequestVO;
|
import com.aizuda.easy.retry.server.web.model.request.WorkflowRequestVO;
|
||||||
|
import com.aizuda.easy.retry.server.web.model.request.WorkflowRequestVO.NodeInfo;
|
||||||
import com.aizuda.easy.retry.server.web.service.WorkflowService;
|
import com.aizuda.easy.retry.server.web.service.WorkflowService;
|
||||||
|
import com.aizuda.easy.retry.server.web.service.convert.WorkflowConverter;
|
||||||
|
import com.aizuda.easy.retry.template.datasource.persistence.mapper.WorkflowMapper;
|
||||||
|
import com.aizuda.easy.retry.template.datasource.persistence.mapper.WorkflowNodeMapper;
|
||||||
|
import com.aizuda.easy.retry.template.datasource.persistence.po.Workflow;
|
||||||
|
import com.aizuda.easy.retry.template.datasource.persistence.po.WorkflowNode;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.graph.GraphBuilder;
|
||||||
|
import com.google.common.graph.MutableGraph;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author xiaowoniu
|
* @author xiaowoniu
|
||||||
@ -10,10 +30,65 @@ import org.springframework.stereotype.Service;
|
|||||||
* @since 2.6.0
|
* @since 2.6.0
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class WorkflowServiceImpl implements WorkflowService {
|
public class WorkflowServiceImpl implements WorkflowService {
|
||||||
|
private final WorkflowMapper workflowMapper;
|
||||||
|
private final WorkflowNodeMapper workflowNodeMapper;
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional
|
||||||
public boolean saveWorkflow(WorkflowRequestVO workflowRequestVO) {
|
public boolean saveWorkflow(WorkflowRequestVO workflowRequestVO) {
|
||||||
return false;
|
|
||||||
|
Long root = -1L;
|
||||||
|
MutableGraph<Long> graph = GraphBuilder.directed().build();
|
||||||
|
// 添加虚拟头节点
|
||||||
|
graph.addNode(root);
|
||||||
|
|
||||||
|
// 组装工作流信息
|
||||||
|
Workflow workflow = WorkflowConverter.INSTANCE.toWorkflow(workflowRequestVO);
|
||||||
|
workflow.setFlowInfo(StrUtil.EMPTY);
|
||||||
|
Assert.isTrue(1 == workflowMapper.insert(workflow), () -> new EasyRetryServerException("新增工作流失败"));
|
||||||
|
|
||||||
|
// 组装节点信息
|
||||||
|
List<NodeInfo> nodeInfos = workflowRequestVO.getNodeInfos();
|
||||||
|
|
||||||
|
// 递归构建图
|
||||||
|
buildGraph(root, workflowRequestVO.getGroupName(), workflow.getId(), nodeInfos, graph);
|
||||||
|
|
||||||
|
// 保存图信息
|
||||||
|
workflow.setFlowInfo(JsonUtil.toJsonString(convertGraphToAdjacencyList(graph)));
|
||||||
|
workflowMapper.updateById(workflow);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<Long, Iterable<Long>> convertGraphToAdjacencyList(MutableGraph<Long> graph) {
|
||||||
|
Map<Long, Iterable<Long>> adjacencyList = new HashMap<>();
|
||||||
|
|
||||||
|
for (Long node : graph.nodes()) {
|
||||||
|
adjacencyList.put(node, graph.successors(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
return adjacencyList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildGraph(Long parentId, String groupName, Long workflowId, List<NodeInfo> nodeInfos, MutableGraph<Long> graph) {
|
||||||
|
|
||||||
|
if (CollectionUtils.isEmpty(nodeInfos)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final NodeInfo nodeInfo : nodeInfos) {
|
||||||
|
WorkflowNode workflowNode = WorkflowConverter.INSTANCE.toWorkflowNode(nodeInfo);
|
||||||
|
workflowNode.setWorkflowId(workflowId);
|
||||||
|
workflowNode.setGroupName(groupName);
|
||||||
|
Assert.isTrue(1 == workflowNodeMapper.insert(workflowNode), () -> new EasyRetryServerException("新增工作流节点失败"));
|
||||||
|
// 添加节点
|
||||||
|
graph.addNode(workflowNode.getId());
|
||||||
|
// 添加边
|
||||||
|
graph.putEdge(parentId, workflowNode.getId());
|
||||||
|
buildGraph(workflowNode.getId(), groupName, workflowId, nodeInfo.getChildreList(), graph);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user