feat: 2.6.0

1. 完成新增接口
This commit is contained in:
byteblogs168 2023-12-13 16:45:12 +08:00
parent 411ceeafc0
commit bd178c0f09
7 changed files with 170 additions and 18 deletions

View File

@ -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、阻塞',

View File

@ -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;
/** /**
* 任务执行时间 * 任务执行时间

View File

@ -44,6 +44,11 @@ public class WorkflowNode implements Serializable {
*/ */
private Long jobId; private Long jobId;
/**
* 工作流ID
*/
private Long workflowId;
/** /**
* 1任务节点 2条件节点 * 1任务节点 2条件节点
*/ */

View File

@ -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);
} }

View File

@ -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;
/**
* 表达式类型 1SpEl2Aviator 3QL
*/
@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;
} }

View File

@ -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);
}

View File

@ -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);
}
}
} }