删除掉nodeDefinition表,因为它暂时用不上。

This commit is contained in:
dengqichen 2024-12-09 10:54:10 +08:00
parent 305759dd67
commit 1d518aa4d3
10 changed files with 29 additions and 449 deletions

View File

@ -1,39 +0,0 @@
package com.qqchen.deploy.backend.workflow.converter;
import com.qqchen.deploy.backend.framework.converter.BaseConverter;
import com.qqchen.deploy.backend.workflow.dto.NodeDefinitionDTO;
import com.qqchen.deploy.backend.workflow.entity.NodeDefinition;
import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
/**
* 节点定义转换器
*/
@Mapper(config = BaseConverter.class)
public interface NodeDefinitionConverter extends BaseConverter<NodeDefinition, NodeDefinitionDTO> {
@Override
@Mapping(target = "workflowDefinitionId", source = "workflowDefinition", qualifiedByName = "getWorkflowDefinitionId")
NodeDefinitionDTO toDto(NodeDefinition entity);
@Override
@Mapping(target = "workflowDefinition", source = "workflowDefinitionId", qualifiedByName = "createWorkflowDefinition")
NodeDefinition toEntity(NodeDefinitionDTO dto);
@Named("getWorkflowDefinitionId")
default Long getWorkflowDefinitionId(WorkflowDefinition workflowDefinition) {
return workflowDefinition != null ? workflowDefinition.getId() : null;
}
@Named("createWorkflowDefinition")
default WorkflowDefinition createWorkflowDefinition(Long id) {
if (id == null) {
return null;
}
WorkflowDefinition workflowDefinition = new WorkflowDefinition();
workflowDefinition.setId(id);
return workflowDefinition;
}
}

View File

@ -1,38 +0,0 @@
package com.qqchen.deploy.backend.workflow.dto;
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* 节点定义DTO用于解析工作流定义中的节点配置
*/
@Data
public class NodeDefinition {
/**
* 节点ID
*/
private String id;
/**
* 节点类型
*/
private NodeTypeEnum type;
/**
* 节点名称
*/
private String name;
/**
* 下一个节点的ID列表
*/
private List<String> next;
/**
* 节点配置不同类型的节点有不同的配置
*/
private Map<String, Object> config;
}

View File

@ -0,0 +1,28 @@
package com.qqchen.deploy.backend.workflow.engine.exception;
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.framework.exception.BusinessException;
import lombok.Getter;
/**
* 工作流节点相关异常
*/
@Getter
public class WorkflowNodeException extends BusinessException {
private final String nodeId;
private final String nodeName;
public WorkflowNodeException(ResponseCode code, String nodeId, String nodeName) {
super(code, new Object[]{nodeId, nodeName});
this.nodeId = nodeId;
this.nodeName = nodeName;
}
public WorkflowNodeException(ResponseCode code, String nodeId, String nodeName, Throwable cause) {
super(code, new Object[]{nodeId, nodeName, cause.getMessage()});
this.nodeId = nodeId;
this.nodeName = nodeName;
}
}

View File

@ -1,14 +1,8 @@
package com.qqchen.deploy.backend.workflow.engine.transition; package com.qqchen.deploy.backend.workflow.engine.transition;
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.context.WorkflowContextOperations;
import com.qqchen.deploy.backend.workflow.engine.exception.WorkflowEngineException;
import com.qqchen.deploy.backend.workflow.entity.NodeDefinition;
import com.qqchen.deploy.backend.workflow.entity.NodeInstance; import com.qqchen.deploy.backend.workflow.entity.NodeInstance;
import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition;
import com.qqchen.deploy.backend.workflow.enums.NodeStatusEnum;
import com.qqchen.deploy.backend.workflow.repository.INodeDefinitionRepository;
import com.qqchen.deploy.backend.workflow.repository.INodeInstanceRepository; import com.qqchen.deploy.backend.workflow.repository.INodeInstanceRepository;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -24,9 +18,6 @@ public class TransitionExecutor {
@Resource @Resource
private TransitionRuleEngine transitionRuleEngine; private TransitionRuleEngine transitionRuleEngine;
@Resource
private INodeDefinitionRepository nodeDefinitionRepository;
@Resource @Resource
private INodeInstanceRepository nodeInstanceRepository; private INodeInstanceRepository nodeInstanceRepository;
@ -37,27 +28,6 @@ public class TransitionExecutor {
// 1. 获取下一个节点ID列表 // 1. 获取下一个节点ID列表
List<String> nextNodeIds = transitionRuleEngine.getNextNodeIds(currentNode, definition, context); List<String> nextNodeIds = transitionRuleEngine.getNextNodeIds(currentNode, definition, context);
// 2. 创建下一个节点实例 //这里应该从WorkflowDefinition类的transitionConfig获取
for (String nodeId : nextNodeIds) {
NodeDefinition nextNodeDef = nodeDefinitionRepository.findByWorkflowDefinitionIdAndNodeIdAndDeletedFalse(
definition.getId(), nodeId);
if (nextNodeDef == null) {
throw new WorkflowEngineException(ResponseCode.WORKFLOW_NODE_NOT_FOUND, "未找到节点定义: " + nodeId);
}
NodeInstance nextNode = new NodeInstance();
nextNode.setWorkflowInstance(currentNode.getWorkflowInstance());
nextNode.setNodeId(nodeId);
nextNode.setNodeType(nextNodeDef.getType());
nextNode.setName(nextNodeDef.getName());
nextNode.setConfig(nextNodeDef.getConfig());
nextNode.setStatus(NodeStatusEnum.PENDING);
nextNode.setCreateTime(LocalDateTime.now());
nodeInstanceRepository.save(nextNode);
context.log(String.format("创建下一个节点实例: %s[%s]", nextNode.getName(), nextNode.getNodeId()),
LogLevelEnum.INFO);
}
} }
} }

View File

@ -1,57 +0,0 @@
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.NodeTypeEnum;
import jakarta.persistence.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 节点定义实体
*/
@Data
@EqualsAndHashCode(callSuper = true)
@jakarta.persistence.Entity
@Table(name = "wf_node_definition")
@LogicDelete
public class NodeDefinition extends Entity<Long> {
/**
* 所属工作流定义
*/
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "workflow_definition_id", nullable = false)
private WorkflowDefinition workflowDefinition;
/**
* 节点ID
*/
@Column(name = "node_id", nullable = false)
private String nodeId;
/**
* 节点名称
*/
@Column(nullable = false)
private String name;
/**
* 节点类型
*/
@Enumerated(EnumType.ORDINAL)
@Column(nullable = false)
private NodeTypeEnum type;
/**
* 节点配置(JSON)
*/
@Column(columnDefinition = "TEXT")
private String config;
/**
* 排序号
*/
@Column(name = "order_num")
private Integer orderNum;
}

View File

@ -1,70 +0,0 @@
package com.qqchen.deploy.backend.workflow.repository;
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
import com.qqchen.deploy.backend.workflow.entity.NodeDefinition;
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnum;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* 节点定义仓库接口
*/
@Repository
public interface INodeDefinitionRepository extends IBaseRepository<NodeDefinition, Long> {
/**
* 根据工作流定义ID查询节点列表
*
* @param workflowDefinitionId 工作流定义ID
* @return 节点列表
*/
@Query("SELECT n FROM NodeDefinition n WHERE n.workflowDefinition.id = :workflowDefinitionId AND n.deleted = false ORDER BY n.orderNum")
List<NodeDefinition> findByWorkflowDefinitionId(@Param("workflowDefinitionId") Long workflowDefinitionId);
/**
* 根据工作流定义ID和节点类型查询节点列表
*
* @param workflowDefinitionId 工作流定义ID
* @param type 节点类型
* @return 节点列表
*/
@Query("SELECT n FROM NodeDefinition n WHERE n.workflowDefinition.id = :workflowDefinitionId AND n.type = :type AND n.deleted = false ORDER BY n.orderNum")
List<NodeDefinition> findByWorkflowDefinitionIdAndType(
@Param("workflowDefinitionId") Long workflowDefinitionId,
@Param("type") NodeTypeEnum type);
/**
* 根据工作流定义ID和节点ID查询节点
*
* @param workflowDefinitionId 工作流定义ID
* @param nodeId 节点ID
* @return 节点定义
*/
@Query("SELECT n FROM NodeDefinition n WHERE n.workflowDefinition.id = :workflowDefinitionId AND n.nodeId = :nodeId AND n.deleted = false")
NodeDefinition findByWorkflowDefinitionIdAndNodeIdAndDeletedFalse(
@Param("workflowDefinitionId") Long workflowDefinitionId,
@Param("nodeId") String nodeId);
/**
* 检查节点ID是否已存在
*
* @param workflowDefinitionId 工作流定义ID
* @param nodeId 节点ID
* @return 是否存在
*/
@Query("SELECT COUNT(n) > 0 FROM NodeDefinition n WHERE n.workflowDefinition.id = :workflowDefinitionId AND n.nodeId = :nodeId AND n.deleted = false")
boolean existsByWorkflowDefinitionIdAndNodeIdAndDeletedFalse(
@Param("workflowDefinitionId") Long workflowDefinitionId,
@Param("nodeId") String nodeId);
/**
* 删除工作流定义的所有节点
*
* @param workflowDefinitionId 工作流定义ID
*/
@Query("UPDATE NodeDefinition n SET n.deleted = true WHERE n.workflowDefinition.id = :workflowDefinitionId")
void deleteByWorkflowDefinitionId(@Param("workflowDefinitionId") Long workflowDefinitionId);
}

View File

@ -7,7 +7,6 @@ import com.qqchen.deploy.backend.workflow.converter.WorkflowDefinitionConverter;
import com.qqchen.deploy.backend.workflow.dto.WorkflowDefinitionDTO; import com.qqchen.deploy.backend.workflow.dto.WorkflowDefinitionDTO;
import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition; import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition;
import com.qqchen.deploy.backend.workflow.enums.WorkflowDefinitionStatusEnum; import com.qqchen.deploy.backend.workflow.enums.WorkflowDefinitionStatusEnum;
import com.qqchen.deploy.backend.workflow.repository.INodeDefinitionRepository;
import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository; import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository;
import com.qqchen.deploy.backend.workflow.service.IWorkflowDefinitionService; import com.qqchen.deploy.backend.workflow.service.IWorkflowDefinitionService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@ -30,9 +29,6 @@ public class WorkflowDefinitionServiceImpl extends BaseServiceImpl<WorkflowDefin
@Resource @Resource
private IWorkflowDefinitionRepository workflowDefinitionRepository; private IWorkflowDefinitionRepository workflowDefinitionRepository;
@Resource
private INodeDefinitionRepository nodeDefinitionRepository;
@Resource @Resource
private WorkflowDefinitionConverter workflowDefinitionConverter; private WorkflowDefinitionConverter workflowDefinitionConverter;

View File

@ -405,28 +405,6 @@ CREATE TABLE wf_workflow_definition (
CONSTRAINT UK_workflow_definition_code_version UNIQUE (code, version_no) CONSTRAINT UK_workflow_definition_code_version UNIQUE (code, version_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工作流定义表'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='工作流定义表';
-- 节点定义表
CREATE TABLE wf_node_definition (
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
create_by VARCHAR(255) NULL COMMENT '创建人',
create_time DATETIME(6) NULL COMMENT '创建时间',
deleted BIT NOT NULL DEFAULT 0 COMMENT '是否删除0未删除1已删除',
update_by VARCHAR(255) NULL COMMENT '更新人',
update_time DATETIME(6) NULL COMMENT '更新时间',
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
workflow_definition_id BIGINT NOT NULL COMMENT '工作流定义ID',
node_id VARCHAR(100) NOT NULL COMMENT '节点ID',
name VARCHAR(100) NOT NULL COMMENT '节点名称',
type TINYINT NOT NULL COMMENT '节点类型0开始节点1结束节点2任务节点3网关节点4子流程节点5Shell脚本节点6审批节点7Jenkins任务节点8Git操作节点',
config TEXT NULL COMMENT '节点配置(JSON)',
description TEXT NULL COMMENT '节点描述',
order_num INT NOT NULL DEFAULT 0 COMMENT '排序号',
CONSTRAINT FK_node_definition_workflow FOREIGN KEY (workflow_definition_id) REFERENCES wf_workflow_definition (id),
CONSTRAINT UK_node_definition_workflow_node UNIQUE (workflow_definition_id, node_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='节点定义表';
-- 流转配置表 -- 流转配置表
CREATE TABLE wf_transition_config ( CREATE TABLE wf_transition_config (
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',

View File

@ -171,32 +171,6 @@ INSERT INTO wf_workflow_definition (
1 1
); );
-- 初始化节点定义
INSERT INTO wf_node_definition (
id, create_by, create_time, deleted, update_by, update_time, version,
workflow_definition_id, node_id, name, type, config, order_num
) VALUES
-- 开始节点
(1, 'admin', NOW(), 0, 'admin', NOW(), 0,
1, 'startNode', '开始', 0,
'{"type":"START","name":"开始"}',
1),
-- 构建节点
(2, 'admin', NOW(), 0, 'admin', NOW(), 0,
1, 'build', '构建', 2,
'{"type":"TASK","name":"构建","executor":"JENKINS","jenkinsJob":"app-build"}',
2),
-- 部署节点
(3, 'admin', NOW(), 0, 'admin', NOW(), 0,
1, 'deploy', '部署', 2,
'{"type":"TASK","name":"部署","executor":"SHELL","script":"./deploy.sh"}',
3),
-- 结束节点
(4, 'admin', NOW(), 0, 'admin', NOW(), 0,
1, 'endNode', '结束', 1,
'{"type":"END","name":"结束"}',
4);
-- 初始化工作流实例 -- 初始化工作流实例
INSERT INTO wf_workflow_instance ( INSERT INTO wf_workflow_instance (
id, create_by, create_time, deleted, update_by, update_time, version, id, create_by, create_time, deleted, update_by, update_time, version,

View File

@ -1,162 +0,0 @@
package com.qqchen.deploy.backend.workflow.service;
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.framework.exception.BusinessException;
import com.qqchen.deploy.backend.workflow.dto.WorkflowDefinitionDTO;
import com.qqchen.deploy.backend.workflow.entity.WorkflowDefinition;
import com.qqchen.deploy.backend.workflow.enums.WorkflowDefinitionStatusEnum;
import com.qqchen.deploy.backend.workflow.repository.INodeDefinitionRepository;
import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository;
import com.qqchen.deploy.backend.workflow.service.impl.WorkflowDefinitionServiceImpl;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Arrays;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class WorkflowDefinitionServiceTest {
@Mock
private IWorkflowDefinitionRepository workflowDefinitionRepository;
@Mock
private INodeDefinitionRepository nodeDefinitionRepository;
@InjectMocks
private WorkflowDefinitionServiceImpl workflowDefinitionService;
private WorkflowDefinitionDTO dto;
private WorkflowDefinition entity;
@BeforeEach
void setUp() {
dto = new WorkflowDefinitionDTO();
dto.setCode("TEST-WF");
dto.setName("Test Workflow");
dto.setDescription("Test Description");
dto.setNodeConfig("{}");
dto.setTransitionConfig("{}");
dto.setFormDefinition("{}");
dto.setGraphDefinition("{}");
entity = new WorkflowDefinition();
entity.setId(1L);
entity.setCode("TEST-WF");
entity.setName("Test Workflow");
entity.setStatus(WorkflowDefinitionStatusEnum.DRAFT);
entity.setEnabled(true);
}
@Test
void create_Success() {
when(workflowDefinitionRepository.existsByCodeAndDeletedFalse(anyString())).thenReturn(false);
when(workflowDefinitionRepository.save(any(WorkflowDefinition.class))).thenReturn(entity);
WorkflowDefinitionDTO result = workflowDefinitionService.create(dto);
assertNotNull(result);
assertEquals(WorkflowDefinitionStatusEnum.DRAFT, result.getStatus());
assertTrue(result.getEnabled());
verify(workflowDefinitionRepository).existsByCodeAndDeletedFalse(dto.getCode());
verify(workflowDefinitionRepository).save(any(WorkflowDefinition.class));
}
@Test
void create_CodeExists_ThrowsException() {
when(workflowDefinitionRepository.existsByCodeAndDeletedFalse(anyString())).thenReturn(true);
BusinessException exception = assertThrows(BusinessException.class,
() -> workflowDefinitionService.create(dto));
assertEquals(ResponseCode.WORKFLOW_CODE_EXISTS, exception.getErrorCode());
}
@Test
void publish_Success() {
entity.setStatus(WorkflowDefinitionStatusEnum.DRAFT);
when(workflowDefinitionRepository.findById(anyLong())).thenReturn(Optional.of(entity));
when(workflowDefinitionRepository.save(any(WorkflowDefinition.class))).thenReturn(entity);
WorkflowDefinitionDTO result = workflowDefinitionService.publish(1L);
assertNotNull(result);
assertEquals(WorkflowDefinitionStatusEnum.PUBLISHED, result.getStatus());
verify(workflowDefinitionRepository).findById(1L);
verify(workflowDefinitionRepository).save(any(WorkflowDefinition.class));
}
@Test
void publish_NotDraft_ThrowsException() {
entity.setStatus(WorkflowDefinitionStatusEnum.PUBLISHED);
when(workflowDefinitionRepository.findById(anyLong())).thenReturn(Optional.of(entity));
BusinessException exception = assertThrows(BusinessException.class,
() -> workflowDefinitionService.publish(1L));
assertEquals(ResponseCode.WORKFLOW_NOT_DRAFT, exception.getErrorCode());
}
@Test
void disable_Success() {
entity.setStatus(WorkflowDefinitionStatusEnum.PUBLISHED);
when(workflowDefinitionRepository.findById(anyLong())).thenReturn(Optional.of(entity));
when(workflowDefinitionRepository.save(any(WorkflowDefinition.class))).thenReturn(entity);
WorkflowDefinitionDTO result = workflowDefinitionService.disable(1L);
assertNotNull(result);
assertEquals(WorkflowDefinitionStatusEnum.DISABLED, result.getStatus());
verify(workflowDefinitionRepository).findById(1L);
verify(workflowDefinitionRepository).save(any(WorkflowDefinition.class));
}
@Test
void enable_Success() {
entity.setStatus(WorkflowDefinitionStatusEnum.DISABLED);
when(workflowDefinitionRepository.findById(anyLong())).thenReturn(Optional.of(entity));
when(workflowDefinitionRepository.save(any(WorkflowDefinition.class))).thenReturn(entity);
WorkflowDefinitionDTO result = workflowDefinitionService.enable(1L);
assertNotNull(result);
assertEquals(WorkflowDefinitionStatusEnum.PUBLISHED, result.getStatus());
verify(workflowDefinitionRepository).findById(1L);
verify(workflowDefinitionRepository).save(any(WorkflowDefinition.class));
}
@Test
void createNewVersion_Success() {
when(workflowDefinitionRepository.findById(anyLong())).thenReturn(Optional.of(entity));
when(workflowDefinitionRepository.findLatestVersionByCode(anyString())).thenReturn(1);
when(workflowDefinitionRepository.save(any(WorkflowDefinition.class))).thenReturn(entity);
WorkflowDefinitionDTO result = workflowDefinitionService.createNewVersion(1L);
assertNotNull(result);
assertEquals(WorkflowDefinitionStatusEnum.DRAFT, result.getStatus());
assertTrue(result.getEnabled());
verify(workflowDefinitionRepository).findById(1L);
verify(workflowDefinitionRepository).findLatestVersionByCode(entity.getCode());
verify(workflowDefinitionRepository).save(any(WorkflowDefinition.class));
}
@Test
void findAllVersions_Success() {
when(workflowDefinitionRepository.findAllVersionsByCode(anyString()))
.thenReturn(Arrays.asList(entity));
var results = workflowDefinitionService.findAllVersions("TEST-WF");
assertNotNull(results);
assertFalse(results.isEmpty());
assertEquals(1, results.size());
verify(workflowDefinitionRepository).findAllVersionsByCode("TEST-WF");
}
}