diff --git a/CHANGELOG.md b/CHANGELOG.md index f9e21c5d..c7b3f800 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,6 @@ All notable changes to this project will be documented in this file. ### Bugfix - Fix v1.1.0 release issues - ## [1.1.0] - 2023-03-15 Support CallActivity configuration and execution. @@ -22,15 +21,11 @@ Add CallActivity Node 1. Optimize Maven dependency management - -Remove httpclient dependency - - -Remove individual jsr250 API dependencies - - -Remove individual junit dependencies - - -Commons collections 3.2.2-->commons collections 4 - - -Commons lang3 3.4-->3.12.0 + - Remove httpclient dependency + - Remove individual jsr250 API dependencies + - Remove individual junit dependencies + - Commons collections 3.2.2-->commons collections 4 + - Commons lang3 3.4-->3.12.0 2. Optimize hook function, change HTTP mode to internal call mode, reduce dependence on HTTP packages, and improve performance diff --git a/README.md b/README.md index 596888e4..3a7ed8a2 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # Turbo 简介 +[![License](https://img.shields.io/github/license/didi/turbo.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![Maven](https://img.shields.io/maven-central/v/com.didiglobal.turbo/turbo.svg)](https://github.com/didi/turbo/releases) + + Turbo是一款Java实现的轻量级流程引擎,是公司内多个低代码平台的核心后端服务。 # 特性 @@ -199,7 +203,7 @@ Turbo的定位是兼容BPMN2.0的轻量级流程引擎(而非平台),支 ``` -## 3. 配置必要信息 +## 2. 配置必要信息 执行[建表语句](engine/src/main/resources/turbo.db.create/turbo.mysql.sql),在属性文件中配置属性信息 @@ -214,7 +218,7 @@ spring.datasource.dynamic.datasource.engine.url=jdbc:mysql://127.0.0.1:3306/db_e ``` -## 4. 根据demo开始你的Turbo之旅吧 +## 3. 根据demo开始你的Turbo之旅吧 根据上文提到的turbo支持的特性,给出了两个例子,其中整体的流程如下图所示: @@ -232,7 +236,7 @@ Demo2:请假流程 注:例子使用两个service是为了封装sop,在实际开发中sop是有前端页面传递进入,并非是必须再次开发。 -## 5. Turbo与LogicFlow交互demo +## 4. Turbo与LogicFlow交互demo LogicFlow 是一款流程图编辑框架,提供了一系列流程图交互、编辑所必需的功能和灵活的节点自定义、插件等拓展机制。使用LogicFlow与Turbo接口交互可实现流程图创建,编辑,保存,发布功能,发布完成流程图即可参考第四部分文档,执行流程。 @@ -246,12 +250,12 @@ LogicFlow 是一款流程图编辑框架,提供了一系列流程图交互、 代码提供基本用法示例,使用方可以根据自己的业务场景参考使用 -## 6. 新的节点类型CallActivity上线啦 +## 5. 新的节点类型CallActivity上线啦 千呼万唤的子流程它来了,着眼于内外部需求,我们新增了调用子流程节点,支持了同步单实例调用子流程 使用文档:[CallActivityGuide](docs/CallActivityGuide.md) -## 7. 联系我们 +## 6. 联系我们 ### 加入微信群 添加微信号:logic-flow 加入turbo用户群 diff --git a/demo/pom.xml b/demo/pom.xml index 9225c30e..80d8d404 100644 --- a/demo/pom.xml +++ b/demo/pom.xml @@ -6,13 +6,13 @@ com.didiglobal.turbo turbo - 1.1.1 + 1.1.2-SNAPSHOT 4.0.0 demo - 1.1.1 + 1.1.2-SNAPSHOT jar @@ -20,8 +20,7 @@ 1.8 1.5.10.RELEASE - 1.1.1 - 1.4.200 + 1.1.2-SNAPSHOT @@ -44,7 +43,6 @@ com.h2database h2 - 1.4.200 test diff --git a/demo/src/main/java/com/didiglobal/turbo/demo/DemoApplication.java b/demo/src/main/java/com/didiglobal/turbo/demo/DemoApplication.java index a929cc66..5c84f18b 100644 --- a/demo/src/main/java/com/didiglobal/turbo/demo/DemoApplication.java +++ b/demo/src/main/java/com/didiglobal/turbo/demo/DemoApplication.java @@ -2,8 +2,6 @@ import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; import com.didiglobal.turbo.engine.annotation.EnableTurboEngine; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; diff --git a/demo/src/main/java/com/didiglobal/turbo/demo/service/HookServiceImpl.java b/demo/src/main/java/com/didiglobal/turbo/demo/service/HookServiceImpl.java index 06988eef..3f43ba69 100644 --- a/demo/src/main/java/com/didiglobal/turbo/demo/service/HookServiceImpl.java +++ b/demo/src/main/java/com/didiglobal/turbo/demo/service/HookServiceImpl.java @@ -1,7 +1,7 @@ package com.didiglobal.turbo.demo.service; import com.didiglobal.turbo.engine.model.InstanceData; -import com.didiglobal.turbo.engine.spi.HookService; +import com.didiglobal.turbo.engine.hook.HookService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; diff --git a/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java b/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java new file mode 100644 index 00000000..9eca54ac --- /dev/null +++ b/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestExpressionCalculator.java @@ -0,0 +1,48 @@ +package com.didiglobal.turbo.demo.spi; + +import com.didiglobal.turbo.engine.exception.ProcessException; +import com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator; +import com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculatorFactory; +import com.google.common.collect.Maps; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.Assert; + +import java.util.Map; + +public class TestExpressionCalculator implements ExpressionCalculator { + + private static final Logger LOGGER = LoggerFactory.getLogger(TestExpressionCalculator.class); + + @Override + public String getType() { + return "test"; + } + + @Override + public Boolean calculate(String expression, Map dataMap) throws ProcessException { + // You can customize the implementation, + // and the code here serves as an example of extending the calculation expression + // Because all calculations in the demo use groovy, the groovy method will also be used here + LOGGER.info("enter TestExpressionCalculator, but use groovy for test"); + return ExpressionCalculatorFactory.getExpressionCalculator("groovy").calculate(expression, dataMap); + } + + /** + * test + * + * @param args + */ + public static void main(String[] args) { + TestExpressionCalculator testExpressionCalculator = new TestExpressionCalculator(); + String expression = "[0-9]"; + Map dataMap = Maps.newHashMap(); + dataMap.put("data", "1"); + try { + Boolean result = testExpressionCalculator.calculate(expression, dataMap); + Assert.isTrue(result, "test fail"); + } catch (ProcessException e) { + e.printStackTrace(); + } + } +} diff --git a/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestIdGenerator.java b/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestIdGenerator.java new file mode 100644 index 00000000..e0c78f2c --- /dev/null +++ b/demo/src/main/java/com/didiglobal/turbo/demo/spi/TestIdGenerator.java @@ -0,0 +1,13 @@ +package com.didiglobal.turbo.demo.spi; + +import com.didiglobal.turbo.engine.spi.generator.IdGenerator; +import org.apache.commons.lang3.RandomStringUtils; + +public class TestIdGenerator implements IdGenerator { + + @Override + public String getNextId() { + // Expand your ID generator in this way + return RandomStringUtils.randomAlphabetic(20); + } +} diff --git a/demo/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator b/demo/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator new file mode 100644 index 00000000..01fc9434 --- /dev/null +++ b/demo/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator @@ -0,0 +1 @@ +com.didiglobal.turbo.demo.spi.TestExpressionCalculator \ No newline at end of file diff --git a/demo/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator b/demo/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator new file mode 100644 index 00000000..2f64f25c --- /dev/null +++ b/demo/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator @@ -0,0 +1 @@ +com.didiglobal.turbo.demo.spi.TestIdGenerator \ No newline at end of file diff --git a/demo/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator b/demo/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator new file mode 100644 index 00000000..e69de29b diff --git a/demo/src/test/resources/application.properties b/demo/src/test/resources/application.properties index 5da0c6bf..6212bae9 100644 --- a/demo/src/test/resources/application.properties +++ b/demo/src/test/resources/application.properties @@ -1,4 +1,4 @@ -# ????? +# h2 spring.datasource.url=jdbc:h2:mem:test spring.datasource.driver-class-name=org.h2.Driver spring.datasource.username=root @@ -12,10 +12,10 @@ spring.datasource.dynamic.datasource.engine.driver-class-name=org.h2.Driver spring.datasource.dynamic.datasource.engine.url=jdbc:h2:mem:t_engine;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE -# DDL?? +# DDL SQL spring.datasource.schema=classpath:script/turbo-mysql-h2-ddl.sql -# DML?? +# DML SQL spring.datasource.data=classpath:script/turbo-mysql-h2-dml.sql logging.config=classpath:logback-spring.xml diff --git a/demo/src/test/resources/script/turbo-mysql-h2-ddl.sql b/demo/src/test/resources/script/turbo-mysql-h2-ddl.sql index f918529f..0647b842 100644 --- a/demo/src/test/resources/script/turbo-mysql-h2-ddl.sql +++ b/demo/src/test/resources/script/turbo-mysql-h2-ddl.sql @@ -1,122 +1,161 @@ CREATE SCHEMA IF NOT EXISTS turbo; DROP TABLE IF EXISTS `em_flow_definition`; -CREATE TABLE IF NOT EXISTS `em_flow_definition` ( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', - `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', - `flow_name` varchar(64) NOT NULL DEFAULT '' COMMENT '流程名称', - `flow_key` varchar(32) NOT NULL DEFAULT '' COMMENT '流程业务标识', - `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', - `flow_model` mediumtext COMMENT '表单定义', - `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.初始态 2.编辑中 3.已下线)', - `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', - `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', - `operator` varchar(32) NOT NULL DEFAULT '' COMMENT '操作人', - `remark` varchar(512) NOT NULL DEFAULT '' COMMENT '备注', - `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', - `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', - `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', - PRIMARY KEY (`id`), - UNIQUE KEY `uniq_flow_module_id` (`flow_module_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='流程定义表'; +CREATE TABLE IF NOT EXISTS `em_flow_definition` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', + `flow_name` varchar(64) NOT NULL DEFAULT '' COMMENT '流程名称', + `flow_key` varchar(32) NOT NULL DEFAULT '' COMMENT '流程业务标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `flow_model` mediumtext COMMENT '表单定义', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.初始态 2.编辑中 3.已下线)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', + `operator` varchar(32) NOT NULL DEFAULT '' COMMENT '操作人', + `remark` varchar(512) NOT NULL DEFAULT '' COMMENT '备注', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_flow_module_id` (`flow_module_id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8 + ROW_FORMAT = COMPACT COMMENT ='流程定义表'; DROP TABLE IF EXISTS `em_flow_deployment`; -CREATE TABLE IF NOT EXISTS `em_flow_deployment` ( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', - `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', - `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', - `flow_name` varchar(64) NOT NULL DEFAULT '' COMMENT '流程名称', - `flow_key` varchar(32) NOT NULL DEFAULT '' COMMENT '流程业务标识', - `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', - `flow_model` mediumtext COMMENT '表单定义', - `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.已部署 3.已下线)', - `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', - `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', - `operator` varchar(32) NOT NULL DEFAULT '' COMMENT '操作人', - `remark` varchar(512) NOT NULL DEFAULT '' COMMENT '备注', - `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', - `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', - `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', +CREATE TABLE IF NOT EXISTS `em_flow_deployment` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', + `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', + `flow_name` varchar(64) NOT NULL DEFAULT '' COMMENT '流程名称', + `flow_key` varchar(32) NOT NULL DEFAULT '' COMMENT '流程业务标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `flow_model` mediumtext COMMENT '表单定义', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.已部署 3.已下线)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', + `operator` varchar(32) NOT NULL DEFAULT '' COMMENT '操作人', + `remark` varchar(512) NOT NULL DEFAULT '' COMMENT '备注', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', PRIMARY KEY (`id`), UNIQUE KEY `uniq_flow_deploy_id` (`flow_deploy_id`), KEY `idx_flow_module_id` (`flow_module_id`) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='流程部署表'; +) ENGINE = InnoDB + DEFAULT CHARSET = utf8 + ROW_FORMAT = COMPACT COMMENT ='流程部署表'; DROP TABLE IF EXISTS `ei_flow_instance`; -CREATE TABLE IF NOT EXISTS `ei_flow_instance` ( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', - `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', - `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', - `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', - `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', - `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.执行完成 2.执行中 3.执行终止(强制终止))', - `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', - `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', - `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', - `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', - `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', +CREATE TABLE IF NOT EXISTS `ei_flow_instance` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', + `parent_flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '父流程执行实例id', + `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', + `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.执行完成 2.执行中 3.执行终止(强制终止))', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', PRIMARY KEY (`id`), UNIQUE KEY `uniq_flow_instance_id` (`flow_instance_id`) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='流程执行实例表'; +) ENGINE = InnoDB + DEFAULT CHARSET = utf8 + ROW_FORMAT = COMPACT COMMENT ='流程执行实例表'; + DROP TABLE IF EXISTS `ei_node_instance`; -CREATE TABLE IF NOT EXISTS `ei_node_instance` ( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', - `node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '节点执行实例id', - `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', - `source_node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '上一个节点执行实例id', - `instance_data_id` varchar(128) NOT NULL DEFAULT '' COMMENT '实例数据id', - `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', - `node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '节点唯一标识', - `source_node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '上一个流程节点唯一标识', - `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', - `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.处理成功 2.处理中 3.处理失败 4.处理已撤销)', - `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', - `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', - `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', - `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', - `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', +CREATE TABLE IF NOT EXISTS `ei_node_instance` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '节点执行实例id', + `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', + `source_node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '上一个节点执行实例id', + `instance_data_id` varchar(128) NOT NULL DEFAULT '' COMMENT '实例数据id', + `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', + `node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '节点唯一标识', + `source_node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '上一个流程节点唯一标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.处理成功 2.处理中 3.处理失败 4.处理已撤销)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', PRIMARY KEY (`id`), UNIQUE KEY `uniq_node_instance_id` (`node_instance_id`), - KEY `idx_fiid_sniid_nk` (`flow_instance_id`,`source_node_instance_id`,`node_key`) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='节点执行实例表'; + KEY `idx_fiid_sniid_nk` (`flow_instance_id`, `source_node_instance_id`, `node_key`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8 + ROW_FORMAT = COMPACT COMMENT ='节点执行实例表'; DROP TABLE IF EXISTS `ei_node_instance_log`; -CREATE TABLE IF NOT EXISTS `ei_node_instance_log` ( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', - `node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '节点执行实例id', - `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', - `instance_data_id` varchar(128) NOT NULL DEFAULT '' COMMENT '实例数据id', - `node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '节点唯一标识', - `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', - `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '操作类型(1.系统执行 2.任务提交 3.任务撤销)', - `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.处理成功 2.处理中 3.处理失败 4.处理已撤销)', - `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', - `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', - `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', - `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', +CREATE TABLE IF NOT EXISTS `ei_node_instance_log` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '节点执行实例id', + `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', + `instance_data_id` varchar(128) NOT NULL DEFAULT '' COMMENT '实例数据id', + `node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '节点唯一标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '操作类型(1.系统执行 2.任务提交 3.任务撤销)', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.处理成功 2.处理中 3.处理失败 4.处理已撤销)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', PRIMARY KEY (`id`) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='节点执行记录表'; +) ENGINE = InnoDB + DEFAULT CHARSET = utf8 + ROW_FORMAT = COMPACT COMMENT ='节点执行记录表'; +-- 在ei_instance_data表中,如果需要存储表情符号, MySQL的建表语句需要切换utf8mb4 DROP TABLE IF EXISTS `ei_instance_data`; -CREATE TABLE IF NOT EXISTS `ei_instance_data` ( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', - `node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '节点执行实例id', - `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', - `instance_data_id` varchar(128) NOT NULL DEFAULT '' COMMENT '实例数据id', - `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', - `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', - `node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '节点唯一标识', - `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', - `instance_data` longtext COMMENT '数据列表json', - `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '操作类型(1.实例初始化 2.系统执行 3.系统主动获取 4.上游更新 5.任务提交 6.任务撤回)', - `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', - `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', - `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', - `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', +CREATE TABLE IF NOT EXISTS `ei_instance_data` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '节点执行实例id', + `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', + `instance_data_id` varchar(128) NOT NULL DEFAULT '' COMMENT '实例数据id', + `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', + `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', + `node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '节点唯一标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `instance_data` longtext COMMENT '数据列表json', + `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '操作类型(1.实例初始化 2.系统执行 3.系统主动获取 4.上游更新 5.任务提交 6.任务撤回)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', PRIMARY KEY (`id`), UNIQUE KEY `uniq_instance_data_id` (`instance_data_id`), KEY `idx_flow_instance_id` (`flow_instance_id`) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='节点执行记录表'; +) ENGINE = InnoDB + DEFAULT CHARSET = utf8 + ROW_FORMAT = COMPACT COMMENT ='节点执行记录表'; --- 在ei_instance_data表中,如果需要存储表情符号, MySQL的建表语句需要切换utf8mb4 \ No newline at end of file +DROP TABLE IF EXISTS `ei_flow_instance_mapping`; +CREATE TABLE `ei_flow_instance_mapping` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', + `node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '节点执行实例id', + `node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '节点唯一标识', + `sub_flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '子流程执行实例id', + `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.执行 2.回滚)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT 'didi' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT 'optimus-prime' COMMENT '调用方', + PRIMARY KEY (`id`), + KEY `idx_fii` (`flow_instance_id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8 + ROW_FORMAT = COMPACT COMMENT ='父子流程实例映射表'; \ No newline at end of file diff --git a/docs/UserGuide.md b/docs/UserGuide.md index fda59c5f..b83b807c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -20,7 +20,7 @@ Turbo是Didi公司开发的轻量级的Java实现的流程引擎 流程定义的内容,可以完整描述一个流程的定义,由FlowElement列表的json组成。下面是一个Demo的例子: -``` +```json { "flowElementList": [ { @@ -101,7 +101,7 @@ Turbo是Didi公司开发的轻量级的Java实现的流程引擎 **构造** -``` +```java StartEvent startEvent = new StartEvent(); // 设置唯一键 startEvent.setKey("StartEvent_1r83q1z"); @@ -128,7 +128,7 @@ startEvent.setOutgoing(outgoings); **构造** -``` +```java EndEvent endEvent = new EndEvent(); // 设置唯一键 endEvent.setKey("EndEvent_0z30kyv"); @@ -163,7 +163,7 @@ endEvent.setIncoming(incomings); **构造** -``` +```java ExclusiveGateway exclusiveGateway = new ExclusiveGateway(); // 设置唯一键 exclusiveGateway.setKey("ExclusiveGateway_0yq2l0s"); @@ -224,7 +224,7 @@ exclusiveGateway.setProperties(properties); **构造** -``` +```java UserTask userTask = new UserTask(); // 设置唯一键 userTask.setKey("UserTask_1eglyg7"); @@ -267,7 +267,7 @@ userTask.setOutgoing(utOutgoings); **构造** -``` +```java CallActivity callActivity = new CallActivity(); // 设置唯一键 callActivity.setKey("CallActivity_0ofi5hg"); @@ -327,7 +327,7 @@ callActivity.setProperties(caProperties); **构造** -``` +```java SequenceFlow sequenceFlow1 = new SequenceFlow(); // 设置唯一键 sequenceFlow1.setKey("SequenceFlow_1lc9xoo"); @@ -369,3 +369,107 @@ sequenceFlow1.setProperties(properties); **约束规则** 顺序流只能有一个入口和一个出口。 + + +# 三、SPI扩展使用手册 + +## 1. Turbo SPI 概述 + +### 扩展性设计理念 +可扩展性是任何一个系统所追求的,对于 Turbo 来说同样使用。 + +#### 什么是可扩展性 +可扩展性是一个重要的设计理念,旨在确保在现有的架构或设计基础之上,当未来因某些方面发生变化时,我们能够以更小的改动来实现系统的增强或变更,同时尽量避免对现有代码的修改。 + +#### 可扩展性的优点 +可扩展性的优点主要表现在模块化设计以及模块之间的松耦合关系,它符合开闭原则,对扩展开放,对修改关闭。即可以在不修改现有代码的情况下,通过添加新的实现来扩展系统功能。 + +#### 扩展实现方式 +一般来说,系统会采用 Factory、IoC、OSGI 等方式管理扩展(插件)生命周期。考虑到后期 Turbo 会剥离Spring,不想强依赖 Spring 等 IoC 容器。所以选择最简单的 Factory 方式管理扩展(插件)。在 Turbo 中,所有内部实现和第三方实现都是平等的。 + +#### Turbo中的可扩展性 +- 平等对待第三方实现,在 Turbo 中,所有内部实现和第三方实现都是平等的,用户可以基于自身业务需求,替换 Turbo 中提供的原生实现。 +- 每个扩展点都只都相对独立,可最大化复用。用户如有扩展需求,只需要对关注的扩展点进行扩展就好,降低了扩展难度。 + +### Turbo 扩展特性 +在 Turbo 中,我们使用的是JDK标准的SPI扩展点发现机制,降低用户扩展难度;目前我们提供了针对 ID生成器 和 表达式计算器 的扩展点,后续将增加更多的可扩展点,以满足广大用户需求。 + +#### Turbo 扩展加载逻辑 +Turbo的加载逻辑相对比较简单,采用了懒加载的形式,在使用时会通过ServiceLoader加载并实例化对应实现,并进行缓存。加载过程可能会损耗一些性能,因此确认不使用的实现可以不进行配置。 + +#### Turbo 中 SPI默认实现说明 +Turbo 支持多种实现并存,但在使用时可能只使用其中一个,因此使用哪一个需要确定。一般情况下,是根据SPI的配置加载顺序来决定的,但某些情况下可能存在顺序的不确定性。在 Turbo 中我们提供了 @SPIOrder 注解,使用其value最小的作为默认实现。只有当存在多个对应注解且value值相同时,会按照加载顺序,使用列表中的第一个。 + + +## 2. Turbo扩展使用说明 + +### ID生成器扩展说明 +ID生成器基于 `IdGenerator` 接口实现,接口中仅存在一个方法,即 `genNextId()`;Turbo提供了默认实现`StrongUuidGenerator`,如果使用方想用其他形式ID生成方式,只需要在自己的项目目录下,实现 `IdGenerator` 接口,并按照SPI配置方式进行配置即可;另外,如果存在多个实现,仅会有一个实现是有效的(参考: Turbo 中 SPI默认实现说明)。 + +代码示例: +```java +package com.didiglobal.turbo.demo.spi; + +import com.didiglobal.turbo.engine.spi.generator.IdGenerator; +import org.apache.commons.lang3.RandomStringUtils; + +public class TestIdGenerator implements IdGenerator { + @Override + public String getNextId() { + // Expand your ID generator + return RandomStringUtils.randomAlphabetic(20); + } +} +``` + +配置示例: +```text +├── src +│ ├── main +│ │ ├── java +│ │ │ └── com +│ │ │ └── didiglobal +│ │ │ └── turbo +│ │ │ └── demo +│ │ │ ├── spi +│ │ │ │ └── TestIdGenerator.java +│ │ └── resources +│ │ ├── META-INF +│ │ │ └── services +│ │ │ └── com.didiglobal.turbo.engine.spi.generator.IdGenerator + + +# 文件内容: +com.didiglobal.turbo.demo.spi.TestIdGenerator +``` + +### 表达式计算器扩展说明 +在流程执行过程中,遇到存在多个出口时,会根据出口顺序流上的表达式来进行判断,最终走向哪一个分支。 +Turbo 中默认支持了 `Groovy` 语言的表达式计算器,同时支持用户自行扩展。进行扩展时, 只需要实现 `ExpressionCalculator` 接口,并根据上下文数据返回对应的结果。如果需要在流程图中支持多种表达式计算器,除了需要给出对应的实现外,仍需要在对应的顺序流的属性信息中添加 `conditiontypesequenceflow` 属性,来确定使用哪种类型的表达式计算器。如果不添加该属性,则使用默认的实现。 + +model 示例: +```json +{ + "flowElementList":[ + ... + + { + "incoming":[ + "UserTask_0cx5f72" + ], + "outgoing":[ + "UserTask_15qhuilv" + ], + "type":1, + "properties":{ + "conditionsequenceflow":"${type==1}", + "conditiontypesequenceflow":"groovy" + }, + "key":"SequenceFlow_0ebra7c" + } + + ... + ] +} +``` +说明: 如果仅使用单一的表达式计算器(配置默认实现),则 `conditiontypesequenceflow` 可以省略。 diff --git a/engine/pom.xml b/engine/pom.xml index cea2d87a..b038625f 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -5,13 +5,13 @@ 4.0.0 engine - 1.1.1 + 1.1.2-SNAPSHOT jar turbo com.didiglobal.turbo - 1.1.1 + 1.1.2-SNAPSHOT 2.3.7 @@ -83,6 +83,16 @@ com.google.guava guava + + org.projectlombok + lombok + provided + + + com.h2database + h2 + test + \ No newline at end of file diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/Constants.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/Constants.java index 0fab830a..ff516da1 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/Constants.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/Constants.java @@ -9,6 +9,7 @@ public class Constants { public static final class ELEMENT_PROPERTIES { public static final String NAME = "name"; public static final String CONDITION = "conditionsequenceflow"; + public static final String CONDITION_TYPE = "conditiontypesequenceflow"; public static final String DEFAULT_CONDITION = "defaultConditions"; public static final String HOOK_INFO_IDS = "hookInfoIds"; public static final String CALL_ACTIVITY_EXECUTE_TYPE = "callActivityExecuteType"; diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/ErrorEnum.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/ErrorEnum.java index 2dcf092b..2f9d75d7 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/ErrorEnum.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/ErrorEnum.java @@ -2,18 +2,18 @@ public enum ErrorEnum { - //1000~1999 非阻断性错误码 + // 1000~1999, non blocking error code SUCCESS(1000, "Success"), REENTRANT_WARNING(1001, "Reentrant warning"), COMMIT_SUSPEND(1002, "Commit task suspend"), ROLLBACK_SUSPEND(1003, "Rollback task suspend"), - //2000~2999 通用业务错误 + // 2000~2999, general business error PARAM_INVALID(2001, "Invalid param"), FLOW_NESTED_LEVEL_EXCEEDED(2002, "Flow nested level exceeded"), FLOW_NESTED_DEAD_LOOP(2003, "Flow nested dead loop"), - //3000~3999 流程定义错误 + // 3000~3999, process definition error DEFINITION_INSERT_INVALID(3001, "Definition insert failed"), DEFINITION_UPDATE_INVALID(3002, "Definition update failed"), @@ -31,18 +31,18 @@ public enum ErrorEnum { EMPTY_SEQUENCE_OUTGOING(3209, "Empty sequence outgoing"), TOO_MANY_DEFAULT_SEQUENCE(3210, "Too many default sequence"), MODEL_UNKNOWN_ELEMENT_KEY(3211, "Unknown element key"), - ELEMENT_TOO_MUCH_INCOMING(3212, "Too many incoming"), - ELEMENT_TOO_MUCH_OUTGOING(3213, "Too many outgoing"), + ELEMENT_TOO_MANY_INCOMING(3212, "Too many incoming"), + ELEMENT_TOO_MANY_OUTGOING(3213, "Too many outgoing"), ELEMENT_LACK_INCOMING(3214, "Element lack incoming"), ELEMENT_LACK_OUTGOING(3215, "Element lack outgoing"), REQUIRED_ELEMENT_ATTRIBUTES(3216, "required element attributes"), MODEL_UNKNOWN_ELEMENT_VALUE(3217, "Unknown element value"), - //4000~4999 流程执行错误 + // 4000~4999, process definition error COMMIT_FAILED(4001, "Commit task failed"), ROLLBACK_FAILED(4002, "Rollback task failed"), - COMMIT_REJECTRD(4003, "Commit rejected, flow is terminate"), - ROLLBACK_REJECTRD(4004, "Rollback rejected, non-running flowInstance to rollback"), + COMMIT_REJECTED(4003, "Commit rejected, flow is terminate"), + ROLLBACK_REJECTED(4004, "Rollback rejected, non-running flowInstance to rollback"), NO_NODE_TO_ROLLBACK(4005, "No node to rollback"), NO_USER_TASK_TO_ROLLBACK(4006, "No userTask to rollback"), GET_FLOW_DEPLOYMENT_FAILED(4007, "Get flowDeployment failed"), @@ -59,10 +59,11 @@ public enum ErrorEnum { GROOVY_CALCULATE_FAILED(4018, "Groovy calculate failed"), GET_CALL_ACTIVITY_MODEL_FAILED(4019, "Get CallActivity model failed"), NO_RECEIVE_SUB_FLOW_INSTANCE(4020, "Do not receive subFlowInstanceId"), + NOT_FOUND_EXPRESSION_CALCULATOR(4021, "Not found expression calculator"), - //5000~5999 系统错误 - //保留错误码 + // 5000~5999, system error + // reserved error code SYSTEM_ERROR(5000, "System error"), FAILED(5001, "Failed"); diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowDefinitionStatus.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowDefinitionStatus.java index 88a19700..973f1f47 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowDefinitionStatus.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowDefinitionStatus.java @@ -1,8 +1,23 @@ package com.didiglobal.turbo.engine.common; public class FlowDefinitionStatus { - public static final int DEFAULT = 0; //数据库默认值 - public static final int INIT = 1; //流程创建, 初始化 - public static final int EDITING = 2; //编辑中 - public static final int DISABLED = 3; //已下线, 暂未使用 + /** + * Db default status + */ + public static final int DEFAULT = 0; + + /** + * Initialize state during process creation + */ + public static final int INIT = 1; + + /** + * Editing + */ + public static final int EDITING = 2; + + /** + * Offline, not currently in use + */ + public static final int DISABLED = 3; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowDeploymentStatus.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowDeploymentStatus.java index 40e24020..6ad80ec8 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowDeploymentStatus.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowDeploymentStatus.java @@ -1,7 +1,19 @@ package com.didiglobal.turbo.engine.common; public class FlowDeploymentStatus { - public static final int DEFAULT = 0; //数据库默认值 - public static final int DEPLOYED = 1; //已部署 - public static final int DISABLED = 3; //已下线, 暂未使用 + + /** + * Db default status + */ + public static final int DEFAULT = 0; + + /** + * Deployed + */ + public static final int DEPLOYED = 1; + + /** + * Offline, not currently in use + */ + public static final int DISABLED = 3; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowInstanceStatus.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowInstanceStatus.java index 69eaf61c..58af3f1b 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowInstanceStatus.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowInstanceStatus.java @@ -1,10 +1,30 @@ package com.didiglobal.turbo.engine.common; public class FlowInstanceStatus { - public static final int DEFAULT = 0; //数据库默认值 - public static final int COMPLETED = 1; //执行完成 - public static final int RUNNING = 2; //执行中 - public static final int TERMINATED = 3; //已终止 - // 新增子流程实例的执行结束的终态,主要是解决从父流程实例回滚到已执行结束的子流程实例的情况 - public static final int END = 4; //执行结束 + + /** + * Process initial state + */ + public static final int DEFAULT = 0; + + /** + * The process is completed normally, final state + */ + public static final int COMPLETED = 1; + + /** + * Process execution, non final state + */ + public static final int RUNNING = 2; + + /** + * Process forced end, final state + */ + public static final int TERMINATED = 3; + + /** + * The final state of the sub process, supporting rollback + */ + public static final int END = 4; + } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowModuleStatus.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowModuleStatus.java index 65ecea16..53cca392 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowModuleStatus.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/FlowModuleStatus.java @@ -1,8 +1,8 @@ package com.didiglobal.turbo.engine.common; public class FlowModuleStatus { - public static final int DEFAULT = 0; //数据库默认值 - public static final int EDITING = 1; //编辑中 - public static final int DEPLOYED = 2; //已部署 - public static final int DISABLED = 3; //已下线, 暂未使用 + public static final int DEFAULT = 0; + public static final int EDITING = 1; + public static final int DEPLOYED = 2; + public static final int DISABLED = 3; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/InstanceDataType.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/InstanceDataType.java index 81881eee..e4af8231 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/InstanceDataType.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/InstanceDataType.java @@ -1,11 +1,43 @@ package com.didiglobal.turbo.engine.common; +/** + * Type of instance data recording + */ public class InstanceDataType { - public static final int DEFAULT = 0; //数据库默认值 - public static final int INIT = 1; //实例初始化 - public static final int EXECUTE = 2; //系统执行 - public static final int HOOK = 3; //系统主动获取 - public static final int UPDATE = 4; //上游更新 - public static final int COMMIT = 5; //任务提交 - public static final int ROLLBACK = 6; //任务回滚(暂时无用, 回滚时不产生新数据, 只修改数据版本号(dbId)) + /** + * Default + */ + public static final int DEFAULT = 0; + + /** + * Instance initialization + */ + public static final int INIT = 1; + + /** + * Flow execute + */ + public static final int EXECUTE = 2; + + /** + * Active acquisition by the system + */ + public static final int HOOK = 3; + + /** + * Invoker actively updates + */ + public static final int UPDATE = 4; + + /** + * Submit Task + */ + public static final int COMMIT = 5; + + /** + * Rollback Task + * Not used. No new data is generated during rollback, + * only the data version number (dbId) is modified + */ + public static final int ROLLBACK = 6; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/NodeInstanceStatus.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/NodeInstanceStatus.java index c76992c3..c292a438 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/NodeInstanceStatus.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/NodeInstanceStatus.java @@ -1,9 +1,9 @@ package com.didiglobal.turbo.engine.common; public class NodeInstanceStatus { - public static final int DEFAULT = 0; //数据库默认值 - public static final int COMPLETED = 1; //处理成功 - public static final int ACTIVE = 2; //处理中 - public static final int FAILED = 3; //处理失败 - public static final int DISABLED = 4; //处理已撤销 + public static final int DEFAULT = 0; + public static final int COMPLETED = 1; + public static final int ACTIVE = 2; + public static final int FAILED = 3; + public static final int DISABLED = 4; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/NodeInstanceType.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/NodeInstanceType.java index 546f330d..c6006a09 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/NodeInstanceType.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/NodeInstanceType.java @@ -1,8 +1,8 @@ package com.didiglobal.turbo.engine.common; public class NodeInstanceType { - public static final int DEFAULT = 0; //数据库默认值 - public static final int EXECUTE = 1; //系统执行 - public static final int COMMIT = 2; //任务提交 - public static final int ROLLBACK = 3; //任务撤销 + public static final int DEFAULT = 0; + public static final int EXECUTE = 1; + public static final int COMMIT = 2; + public static final int ROLLBACK = 3; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/ProcessStatus.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/ProcessStatus.java index 1cf89d66..70a2ee42 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/ProcessStatus.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/ProcessStatus.java @@ -1,7 +1,14 @@ package com.didiglobal.turbo.engine.common; public class ProcessStatus { - public static final int DEFAULT = 0; //数据库默认值 - public static final int SUCCESS = 1; //已完成 - public static final int FAILED = 3; //已撤销 + public static final int DEFAULT = 0; + /** + * Processing completed + */ + public static final int SUCCESS = 1; + + /** + * Processing revoked + */ + public static final int FAILED = 3; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/RedisConstants.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/RedisConstants.java deleted file mode 100644 index 9ec48ae2..00000000 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/RedisConstants.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.didiglobal.turbo.engine.common; - -public class RedisConstants { - - public static final String REDIS_PREFIX = "ior:"; //basic - - //k=flowDeployId; v=deployId+flowModuleId+tenantId+flowModel - public static final String FLOW_INFO = REDIS_PREFIX + "flow_info_"; - - //k=flowInstanceId; v=flowInstanceId+deployId+status - public static final String FLOW_INSTANCE = REDIS_PREFIX + "flow_instance_"; - - public static final int FLOW_EXPIRED_SECOND = 30 * 24 * 60 * 60; //30 days - - public static final int FLOW_INSTANCE_EXPIRED_SECOND = 24 * 60 * 60; //1 day -} diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/common/RuntimeContext.java b/engine/src/main/java/com/didiglobal/turbo/engine/common/RuntimeContext.java index 70c4860c..5d50e059 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/common/RuntimeContext.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/common/RuntimeContext.java @@ -26,9 +26,12 @@ public class RuntimeContext { //2.1 flowInstance info private String flowInstanceId; private int flowInstanceStatus; - private NodeInstanceBO suspendNodeInstance; //point to the userTaskInstance to commit/rollback - private List nodeInstanceList; //processed nodeInstance list - private Stack suspendNodeInstanceStack; // suspendNodeInstance Stack: commitNode > ... > currentNode + //point to the userTaskInstance to commit/rollback + private NodeInstanceBO suspendNodeInstance; + //processed nodeInstance list + private List nodeInstanceList; + // suspendNodeInstance Stack: commitNode > ... > currentNode + private Stack suspendNodeInstanceStack; //2.2 current info private FlowElement currentNodeModel; diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/exception/TurboException.java b/engine/src/main/java/com/didiglobal/turbo/engine/exception/TurboException.java index 0022696e..53acb910 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/exception/TurboException.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/exception/TurboException.java @@ -4,7 +4,7 @@ import java.text.MessageFormat; -public class TurboException extends Exception { +public class TurboException extends RuntimeException { private static final String ERROR_MSG_FORMAT = "{0}({1})"; diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java b/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java index 1efecfde..9a75c929 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/executor/ElementExecutor.java @@ -12,7 +12,7 @@ import com.didiglobal.turbo.engine.exception.SuspendException; import com.didiglobal.turbo.engine.model.FlowElement; import com.didiglobal.turbo.engine.model.InstanceData; -import com.didiglobal.turbo.engine.util.ExpressionCalculator; +import com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculatorFactory; import com.didiglobal.turbo.engine.util.FlowModelUtil; import com.didiglobal.turbo.engine.util.InstanceDataUtil; import org.apache.commons.lang3.StringUtils; @@ -20,7 +20,6 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; -import javax.annotation.Resource; import java.util.List; import java.util.Map; @@ -28,9 +27,6 @@ public abstract class ElementExecutor extends RuntimeExecutor { private static final Logger LOGGER = LoggerFactory.getLogger(ElementExecutor.class); - @Resource - protected ExpressionCalculator expressionCalculator; - @Override public void execute(RuntimeContext runtimeContext) throws ProcessException { try { @@ -300,7 +296,8 @@ private FlowElement calculateOutgoing(FlowElement flowElement, Map instanceDataMap) throws ProcessException { + protected boolean processCondition(String type, String expression, Map instanceDataMap) throws ProcessException { Map dataMap = InstanceDataUtil.parseInstanceDataMap(instanceDataMap); - return expressionCalculator.calculate(expression, dataMap); + return ExpressionCalculatorFactory.getExpressionCalculator(type).calculate( expression, dataMap); } } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/executor/ExclusiveGatewayExecutor.java b/engine/src/main/java/com/didiglobal/turbo/engine/executor/ExclusiveGatewayExecutor.java index 10134b59..674d898d 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/executor/ExclusiveGatewayExecutor.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/executor/ExclusiveGatewayExecutor.java @@ -8,7 +8,7 @@ import com.didiglobal.turbo.engine.exception.ProcessException; import com.didiglobal.turbo.engine.model.FlowElement; import com.didiglobal.turbo.engine.model.InstanceData; -import com.didiglobal.turbo.engine.spi.HookService; +import com.didiglobal.turbo.engine.hook.HookService; import com.didiglobal.turbo.engine.util.FlowModelUtil; import com.didiglobal.turbo.engine.util.InstanceDataUtil; import com.google.common.collect.Lists; diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/executor/RuntimeExecutor.java b/engine/src/main/java/com/didiglobal/turbo/engine/executor/RuntimeExecutor.java index 54d45322..40025aff 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/executor/RuntimeExecutor.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/executor/RuntimeExecutor.java @@ -2,19 +2,17 @@ import com.didiglobal.turbo.engine.common.RuntimeContext; -import com.didiglobal.turbo.engine.dao.FlowInstanceMappingDAO; -import com.didiglobal.turbo.engine.dao.InstanceDataDAO; -import com.didiglobal.turbo.engine.dao.NodeInstanceDAO; -import com.didiglobal.turbo.engine.dao.NodeInstanceLogDAO; -import com.didiglobal.turbo.engine.dao.ProcessInstanceDAO; +import com.didiglobal.turbo.engine.dao.*; import com.didiglobal.turbo.engine.exception.ProcessException; -import com.didiglobal.turbo.engine.util.IdGenerator; -import com.didiglobal.turbo.engine.util.StrongUuidGenerator; +import com.didiglobal.turbo.engine.spi.generator.IdGenerateFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Resource; +/** + * runtime executor + */ public abstract class RuntimeExecutor { protected static final Logger LOGGER = LoggerFactory.getLogger(RuntimeExecutor.class); @@ -34,30 +32,72 @@ public abstract class RuntimeExecutor { @Resource protected NodeInstanceLogDAO nodeInstanceLogDAO; - private static final IdGenerator ID_GENERATOR = new StrongUuidGenerator(); @Resource protected FlowInstanceMappingDAO flowInstanceMappingDAO; - private static final IdGenerator idGenerator = new StrongUuidGenerator(); - - protected String genId() { - return ID_GENERATOR.getNextId(); + return IdGenerateFactory.getIdGenerator().getNextId(); } + /** + * Execute the process + * + * @param runtimeContext runtime context information + * @throws ProcessException the exception thrown during execution + */ public abstract void execute(RuntimeContext runtimeContext) throws ProcessException; + /** + * Commit and continue the process + * + * @param runtimeContext runtime context information + * @throws ProcessException the exception thrown during execution + */ public abstract void commit(RuntimeContext runtimeContext) throws ProcessException; + /** + * Roll back to the previous user node + * + * @param runtimeContext runtime context information + * @throws ProcessException the exception thrown during execution + */ public abstract void rollback(RuntimeContext runtimeContext) throws ProcessException; + /** + * Determine whether the process has been completed + * + * @param runtimeContext runtime context information + * @return true or false + * @throws ProcessException the exception thrown during execution + */ protected abstract boolean isCompleted(RuntimeContext runtimeContext) throws ProcessException; + /** + * Determine whether the current process is a sub process + * + * @param runtimeContext runtime context information + * @return true or false + * @throws ProcessException the exception thrown during execution + */ protected boolean isSubFlowInstance(RuntimeContext runtimeContext) throws ProcessException { return runtimeContext.getParentRuntimeContext() != null; } + /** + * Get the current execute executor + * + * @param runtimeContext runtime context information + * @return execute executor + * @throws ProcessException the exception thrown during execution + */ protected abstract RuntimeExecutor getExecuteExecutor(RuntimeContext runtimeContext) throws ProcessException; + /** + * Get the rollback executor + * + * @param runtimeContext runtime context information + * @return rollback executor + * @throws ProcessException the exception thrown during execution + */ protected abstract RuntimeExecutor getRollbackExecutor(RuntimeContext runtimeContext) throws ProcessException; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/HookService.java b/engine/src/main/java/com/didiglobal/turbo/engine/hook/HookService.java similarity index 82% rename from engine/src/main/java/com/didiglobal/turbo/engine/spi/HookService.java rename to engine/src/main/java/com/didiglobal/turbo/engine/hook/HookService.java index 83c5eb4e..3aed1369 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/spi/HookService.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/hook/HookService.java @@ -1,16 +1,9 @@ -package com.didiglobal.turbo.engine.spi; +package com.didiglobal.turbo.engine.hook; import com.didiglobal.turbo.engine.model.InstanceData; import java.util.List; -/** - *

HookService

- * - * @author lijinghao - * @version v1.0 - * @date 2023/2/16 6:59 PM - */ public interface HookService { /** diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/model/FlowElement.java b/engine/src/main/java/com/didiglobal/turbo/engine/model/FlowElement.java index 4907f662..9a72a297 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/model/FlowElement.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/model/FlowElement.java @@ -6,12 +6,31 @@ import java.util.Map; public class FlowElement { - private String key; // 流程内元素唯一key resourceId - private int type; // stencil 类型 - private List outgoing; - private Map properties; // 配置属性 + /** + * Unique key in flow element, resourceId + */ + private String key; + + /** + * The type of element + */ + private int type; + + /** + * List of elements before the current element + */ private List incoming; + /** + * List of elements following the current element + */ + private List outgoing; + + /** + * Element configuration attributes, which can be used to extend + */ + private Map properties; + public String getKey() { return key; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/processor/DefinitionProcessor.java b/engine/src/main/java/com/didiglobal/turbo/engine/processor/DefinitionProcessor.java index 8bc46a74..ab791290 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/processor/DefinitionProcessor.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/processor/DefinitionProcessor.java @@ -16,9 +16,12 @@ import com.didiglobal.turbo.engine.param.DeployFlowParam; import com.didiglobal.turbo.engine.param.GetFlowModuleParam; import com.didiglobal.turbo.engine.param.UpdateFlowParam; -import com.didiglobal.turbo.engine.result.*; -import com.didiglobal.turbo.engine.util.IdGenerator; -import com.didiglobal.turbo.engine.util.StrongUuidGenerator; +import com.didiglobal.turbo.engine.result.CommonResult; +import com.didiglobal.turbo.engine.result.CreateFlowResult; +import com.didiglobal.turbo.engine.result.DeployFlowResult; +import com.didiglobal.turbo.engine.result.FlowModuleResult; +import com.didiglobal.turbo.engine.result.UpdateFlowResult; +import com.didiglobal.turbo.engine.spi.generator.IdGenerateFactory; import com.didiglobal.turbo.engine.validator.ModelValidator; import com.didiglobal.turbo.engine.validator.ParamValidator; import org.apache.commons.lang3.StringUtils; @@ -28,6 +31,7 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; + import java.util.Date; @Component @@ -35,8 +39,6 @@ public class DefinitionProcessor { private static final Logger LOGGER = LoggerFactory.getLogger(DefinitionProcessor.class); - private static final IdGenerator idGenerator = new StrongUuidGenerator(); - @Resource private ModelValidator modelValidator; @@ -53,7 +55,7 @@ public CreateFlowResult create(CreateFlowParam createFlowParam) { FlowDefinitionPO flowDefinitionPO = new FlowDefinitionPO(); BeanUtils.copyProperties(createFlowParam, flowDefinitionPO); - String flowModuleId = idGenerator.getNextId(); + String flowModuleId = IdGenerateFactory.getIdGenerator().getNextId(); flowDefinitionPO.setFlowModuleId(flowModuleId); flowDefinitionPO.setStatus(FlowDefinitionStatus.INIT); Date date = new Date(); @@ -118,7 +120,7 @@ public DeployFlowResult deploy(DeployFlowParam deployFlowParam) { FlowDeploymentPO flowDeploymentPO = new FlowDeploymentPO(); BeanUtils.copyProperties(flowDefinitionPO, flowDeploymentPO); - String flowDeployId = idGenerator.getNextId(); + String flowDeployId = IdGenerateFactory.getIdGenerator().getNextId(); flowDeploymentPO.setFlowDeployId(flowDeployId); flowDeploymentPO.setStatus(FlowDeploymentStatus.DEPLOYED); diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/processor/RuntimeProcessor.java b/engine/src/main/java/com/didiglobal/turbo/engine/processor/RuntimeProcessor.java index 5da6ac51..fdbdb0d0 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/processor/RuntimeProcessor.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/processor/RuntimeProcessor.java @@ -2,27 +2,13 @@ import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.TypeReference; -import com.didiglobal.turbo.engine.bo.ElementInstance; -import com.didiglobal.turbo.engine.bo.FlowInfo; -import com.didiglobal.turbo.engine.bo.FlowInstanceBO; -import com.didiglobal.turbo.engine.bo.NodeInstance; -import com.didiglobal.turbo.engine.bo.NodeInstanceBO; -import com.didiglobal.turbo.engine.common.ErrorEnum; -import com.didiglobal.turbo.engine.common.FlowElementType; -import com.didiglobal.turbo.engine.common.FlowInstanceMappingType; -import com.didiglobal.turbo.engine.common.FlowInstanceStatus; -import com.didiglobal.turbo.engine.common.NodeInstanceStatus; -import com.didiglobal.turbo.engine.common.ProcessStatus; -import com.didiglobal.turbo.engine.common.RuntimeContext; +import com.didiglobal.turbo.engine.bo.*; +import com.didiglobal.turbo.engine.common.*; import com.didiglobal.turbo.engine.dao.FlowDeploymentDAO; import com.didiglobal.turbo.engine.dao.FlowInstanceMappingDAO; import com.didiglobal.turbo.engine.dao.NodeInstanceDAO; import com.didiglobal.turbo.engine.dao.ProcessInstanceDAO; -import com.didiglobal.turbo.engine.entity.FlowDeploymentPO; -import com.didiglobal.turbo.engine.entity.FlowInstanceMappingPO; -import com.didiglobal.turbo.engine.entity.FlowInstancePO; -import com.didiglobal.turbo.engine.entity.InstanceDataPO; -import com.didiglobal.turbo.engine.entity.NodeInstancePO; +import com.didiglobal.turbo.engine.entity.*; import com.didiglobal.turbo.engine.exception.ProcessException; import com.didiglobal.turbo.engine.exception.ReentrantException; import com.didiglobal.turbo.engine.exception.TurboException; @@ -32,16 +18,7 @@ import com.didiglobal.turbo.engine.param.CommitTaskParam; import com.didiglobal.turbo.engine.param.RollbackTaskParam; import com.didiglobal.turbo.engine.param.StartProcessParam; -import com.didiglobal.turbo.engine.result.CommitTaskResult; -import com.didiglobal.turbo.engine.result.ElementInstanceListResult; -import com.didiglobal.turbo.engine.result.FlowInstanceResult; -import com.didiglobal.turbo.engine.result.InstanceDataListResult; -import com.didiglobal.turbo.engine.result.NodeInstanceListResult; -import com.didiglobal.turbo.engine.result.NodeInstanceResult; -import com.didiglobal.turbo.engine.result.RollbackTaskResult; -import com.didiglobal.turbo.engine.result.RuntimeResult; -import com.didiglobal.turbo.engine.result.StartProcessResult; -import com.didiglobal.turbo.engine.result.TerminateResult; +import com.didiglobal.turbo.engine.result.*; import com.didiglobal.turbo.engine.service.FlowInstanceService; import com.didiglobal.turbo.engine.service.InstanceDataService; import com.didiglobal.turbo.engine.service.NodeInstanceService; @@ -59,12 +36,7 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Stack; +import java.util.*; @Component public class RuntimeProcessor { @@ -166,7 +138,7 @@ public CommitTaskResult commit(CommitTaskParam commitTaskParam) { //3.check status if (flowInstanceBO.getStatus() == FlowInstanceStatus.TERMINATED) { LOGGER.warn("commit failed: flowInstance has been completed.||commitTaskParam={}", commitTaskParam); - throw new ProcessException(ErrorEnum.COMMIT_REJECTRD); + throw new ProcessException(ErrorEnum.COMMIT_REJECTED); } if (flowInstanceBO.getStatus() == FlowInstanceStatus.COMPLETED) { LOGGER.warn("commit: reentrant process.||commitTaskParam={}", commitTaskParam); @@ -256,7 +228,7 @@ public RollbackTaskResult rollback(RollbackTaskParam rollbackTaskParam) { if ((flowInstanceBO.getStatus() != FlowInstanceStatus.RUNNING) && (flowInstanceBO.getStatus() != FlowInstanceStatus.END)) { LOGGER.warn("rollback failed: invalid status to rollback.||rollbackTaskParam={}||status={}", rollbackTaskParam, flowInstanceBO.getStatus()); - throw new ProcessException(ErrorEnum.ROLLBACK_REJECTRD); + throw new ProcessException(ErrorEnum.ROLLBACK_REJECTED); } String flowDeployId = flowInstanceBO.getFlowDeployId(); diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/SPIOrder.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/SPIOrder.java new file mode 100644 index 00000000..f4382d9a --- /dev/null +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/SPIOrder.java @@ -0,0 +1,21 @@ +package com.didiglobal.turbo.engine.spi; + +import java.lang.annotation.*; + +/** + * Used to specify SPI order. + * @author lijinghao + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface SPIOrder { + + /** + * The smallest order will be used as the default implementation, + * and if the orders are the same, + * the outermost loaded one will be used as the default implementation + * + * @return order value + */ + int value() default Integer.MAX_VALUE; +} diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java new file mode 100644 index 00000000..8c2c37bf --- /dev/null +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/TurboServiceLoader.java @@ -0,0 +1,70 @@ +package com.didiglobal.turbo.engine.spi; + +import com.google.common.base.Preconditions; +import lombok.Getter; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +/** + * turbo service loader + * + * @param the type of service + * @author lijinghao + */ +public class TurboServiceLoader { + + private static final Map, TurboServiceLoader> LOADERS = new ConcurrentHashMap<>(); + + private final Class serviceInterface; + + @Getter + private final Collection services; + + private TurboServiceLoader(final Class serviceInterface) { + this.serviceInterface = serviceInterface; + validate(); + services = load(); + } + + private Collection load() { + Collection result = new LinkedList<>(); + for (T each : ServiceLoader.load(serviceInterface)) { + result.add(each); + } + return result; + } + + private void validate() { + Preconditions.checkNotNull(serviceInterface, "SPI interface is null."); + Preconditions.checkArgument(serviceInterface.isInterface(), + "SPI interface `%s` is not interface.", serviceInterface); + } + + @SuppressWarnings("unchecked") + public static Collection getServiceInterfaces(final Class serviceInterface) { + TurboServiceLoader result = LOADERS.get(serviceInterface); + return (Collection) (result != null ? result.getServiceInterfaces() + : LOADERS.computeIfAbsent(serviceInterface, TurboServiceLoader::new).getServiceInterfaces()); + } + + private Collection getServiceInterfaces() { + return services; + } + + public static T getDefaultService(Class tClass) { + Collection serviceInterfaces = getServiceInterfaces(tClass); + if (serviceInterfaces.size() == 0) { + throw new RuntimeException("spi load exception: not found Implementation class of interface " + tClass.getName()); + } else if (serviceInterfaces.size() == 1) { + return serviceInterfaces.stream().findFirst().get(); + } else { + // Find the implementation to be used + Optional optionalIdGenerator = serviceInterfaces.stream() + .filter(s -> null != s.getClass().getAnnotation(SPIOrder.class)) + .min(Comparator.comparingInt(o -> o.getClass().getAnnotation(SPIOrder.class).value())); + return optionalIdGenerator.orElseGet(() -> serviceInterfaces.stream().findFirst().get()); + } + } +} + diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/util/ExpressionCalculator.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculator.java similarity index 60% rename from engine/src/main/java/com/didiglobal/turbo/engine/util/ExpressionCalculator.java rename to engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculator.java index 2a854c71..2d0d6563 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/util/ExpressionCalculator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculator.java @@ -1,18 +1,28 @@ -package com.didiglobal.turbo.engine.util; +package com.didiglobal.turbo.engine.spi.calculator; import com.didiglobal.turbo.engine.exception.ProcessException; import java.util.Map; +/** + * turbo outgoing condition calculator + */ public interface ExpressionCalculator { + /** + * Get expression calculator Type + * + * @return expression calculator Type + */ + String getType(); + /** * Execute the conditional expression and get the result of the evaluation * * @param expression conditional expression * @param dataMap data for calculate * @return true or false - * @throws ProcessException + * @throws ProcessException the exception thrown during execution */ Boolean calculate(String expression, Map dataMap) throws ProcessException; } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactory.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactory.java new file mode 100644 index 00000000..5dbb20ab --- /dev/null +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactory.java @@ -0,0 +1,71 @@ +package com.didiglobal.turbo.engine.spi.calculator; + +import com.didiglobal.turbo.engine.common.ErrorEnum; +import com.didiglobal.turbo.engine.exception.TurboException; +import com.didiglobal.turbo.engine.spi.TurboServiceLoader; +import org.apache.commons.lang3.StringUtils; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * expression calculator factory + */ +public class ExpressionCalculatorFactory { + + /** + * default expression calculator + */ + private volatile static ExpressionCalculator DEFAULT_EXPRESSION_CALCULATOR; + + /** + * all calculators + */ + private static final Map CALCULATORS = new LinkedHashMap<>(); + + public static void load() { + Collection serviceInterfaces = TurboServiceLoader.getServiceInterfaces(ExpressionCalculator.class); + serviceInterfaces.forEach(service -> CALCULATORS.put(service.getType(), service)); + } + + public static void loadDefault() { + if (DEFAULT_EXPRESSION_CALCULATOR == null) { + synchronized (ExpressionCalculatorFactory.class) { + if (DEFAULT_EXPRESSION_CALCULATOR == null) { + DEFAULT_EXPRESSION_CALCULATOR = TurboServiceLoader.getDefaultService(ExpressionCalculator.class); + } + } + } + } + + public static boolean contains(String type) { + return CALCULATORS.containsKey(type); + } + + /** + * Get the calculator by type + *

+ * If no type is passed in, use the first calculator loaded by SPI + * + * @param type type of calculator + * @return ExpressionCalculator + */ + public static ExpressionCalculator getExpressionCalculator(String type) { + if (StringUtils.isBlank(type)) { + loadDefault(); + return DEFAULT_EXPRESSION_CALCULATOR; + } + + if (CALCULATORS.isEmpty()) { + load(); + } + + if (!contains(type)) { + throw new TurboException(ErrorEnum.NOT_FOUND_EXPRESSION_CALCULATOR, + String.format("Not found expression calculator for %s", type)); + } + return CALCULATORS.get(type); + } + +} diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/util/impl/GroovyExpressionCalculator.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/GroovyExpressionCalculator.java similarity index 82% rename from engine/src/main/java/com/didiglobal/turbo/engine/util/impl/GroovyExpressionCalculator.java rename to engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/GroovyExpressionCalculator.java index bbafe930..07b8abd9 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/util/impl/GroovyExpressionCalculator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/calculator/GroovyExpressionCalculator.java @@ -1,23 +1,32 @@ -package com.didiglobal.turbo.engine.util.impl; +package com.didiglobal.turbo.engine.spi.calculator; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.didiglobal.turbo.engine.common.ErrorEnum; import com.didiglobal.turbo.engine.exception.ProcessException; -import com.didiglobal.turbo.engine.util.ExpressionCalculator; import com.didiglobal.turbo.engine.util.GroovyUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; import java.text.MessageFormat; import java.util.Map; -@Service +/** + * Implementation of calculator that uses script based on `Groovy` + *

+ * Expressions can be wrapped with ${} or written without anything + * ep: + * ${key_test > 0} or key_test > 0 + */ public class GroovyExpressionCalculator implements ExpressionCalculator { private static final Logger LOGGER = LoggerFactory.getLogger(GroovyExpressionCalculator.class); + @Override + public String getType() { + return "groovy"; + } + @Override public Boolean calculate(String expression, Map dataMap) throws ProcessException { if (expression.startsWith("${") && expression.endsWith("}")) { @@ -30,7 +39,7 @@ public Boolean calculate(String expression, Map dataMap) throws return (Boolean) result; } else { LOGGER.warn("the result of expression is not boolean.||expression={}||result={}||dataMap={}", - expression, result, JSON.toJSONString(dataMap)); + expression, result, JSON.toJSONString(dataMap)); throw new ProcessException(ErrorEnum.GROOVY_CALCULATE_FAILED.getErrNo(), "expression is not instanceof bool."); } } catch (Exception e) { diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java new file mode 100644 index 00000000..d95014dd --- /dev/null +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactory.java @@ -0,0 +1,29 @@ +package com.didiglobal.turbo.engine.spi.generator; + +import com.didiglobal.turbo.engine.spi.TurboServiceLoader; + +/** + * id generate factory + */ +public class IdGenerateFactory { + + /** + * id generator + */ + private volatile static IdGenerator ID_GENERATOR; + + public static IdGenerator getIdGenerator() { + loadDefault(); + return ID_GENERATOR; + } + + private static void loadDefault() { + if (ID_GENERATOR == null) { + synchronized (IdGenerateFactory.class) { + if (ID_GENERATOR == null) { + ID_GENERATOR = TurboServiceLoader.getDefaultService(IdGenerator.class); + } + } + } + } +} diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerator.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerator.java new file mode 100644 index 00000000..da248d48 --- /dev/null +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/IdGenerator.java @@ -0,0 +1,15 @@ +package com.didiglobal.turbo.engine.spi.generator; + +/** + * turbo id generator + */ +public interface IdGenerator { + + /** + * get the next ID + * + * @return ID + */ + String getNextId(); + +} diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/util/StrongUuidGenerator.java b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/StrongUuidGenerator.java similarity index 78% rename from engine/src/main/java/com/didiglobal/turbo/engine/util/StrongUuidGenerator.java rename to engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/StrongUuidGenerator.java index 521c509b..b6519b17 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/util/StrongUuidGenerator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/spi/generator/StrongUuidGenerator.java @@ -1,9 +1,14 @@ -package com.didiglobal.turbo.engine.util; +package com.didiglobal.turbo.engine.spi.generator; +import com.didiglobal.turbo.engine.spi.SPIOrder; import com.fasterxml.uuid.EthernetAddress; import com.fasterxml.uuid.Generators; import com.fasterxml.uuid.impl.TimeBasedGenerator; +/** + * Implementation of UUID generator that uses time/location based generation method + */ +@SPIOrder public final class StrongUuidGenerator implements IdGenerator { private static volatile TimeBasedGenerator timeBasedGenerator; @@ -22,8 +27,8 @@ private void initGenerator() { } } + @Override public String getNextId() { return timeBasedGenerator.generate().toString(); } - } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/util/FlowModelUtil.java b/engine/src/main/java/com/didiglobal/turbo/engine/util/FlowModelUtil.java index f79e33a3..bf0c8402 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/util/FlowModelUtil.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/util/FlowModelUtil.java @@ -107,6 +107,12 @@ public static String getConditionFromSequenceFlow(FlowElement flowElement) { return (String) properties.get(Constants.ELEMENT_PROPERTIES.CONDITION); } + public static String getCalculatorTypeFromSequenceFlow(FlowElement flowElement) { + Map properties = flowElement.getProperties(); + Object type = properties.get(Constants.ELEMENT_PROPERTIES.CONDITION_TYPE); + return type == null ? StringUtils.EMPTY : (String) type; + } + public static boolean isDefaultCondition(FlowElement flowElement) { Map properties = flowElement.getProperties(); String isDefaultStr = (String) properties.get(Constants.ELEMENT_PROPERTIES.DEFAULT_CONDITION); diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/util/IdGenerator.java b/engine/src/main/java/com/didiglobal/turbo/engine/util/IdGenerator.java deleted file mode 100644 index 00067001..00000000 --- a/engine/src/main/java/com/didiglobal/turbo/engine/util/IdGenerator.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.didiglobal.turbo.engine.util; - -public interface IdGenerator { - - String getNextId(); - -} diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/validator/CallActivityValidator.java b/engine/src/main/java/com/didiglobal/turbo/engine/validator/CallActivityValidator.java index 33f4b289..4031fd83 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/validator/CallActivityValidator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/validator/CallActivityValidator.java @@ -64,7 +64,7 @@ protected void checkOutgoing(Map flowElementMap, FlowElemen List outgoingList = flowElement.getOutgoing(); if (outgoingList.size() != 1) { - throwElementValidatorException(flowElement, ErrorEnum.ELEMENT_TOO_MUCH_OUTGOING); + throwElementValidatorException(flowElement, ErrorEnum.ELEMENT_TOO_MANY_OUTGOING); } } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/validator/EndEventValidator.java b/engine/src/main/java/com/didiglobal/turbo/engine/validator/EndEventValidator.java index b9bd67e3..965eb008 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/validator/EndEventValidator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/validator/EndEventValidator.java @@ -25,7 +25,7 @@ protected void checkOutgoing(Map flowElementMap, FlowElemen List outgoing = flowElement.getOutgoing(); if (CollectionUtils.isNotEmpty(outgoing)) { - recordElementValidatorException(flowElement, ErrorEnum.ELEMENT_TOO_MUCH_OUTGOING); + recordElementValidatorException(flowElement, ErrorEnum.ELEMENT_TOO_MANY_OUTGOING); } } } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/validator/SequenceFlowValidator.java b/engine/src/main/java/com/didiglobal/turbo/engine/validator/SequenceFlowValidator.java index bb6aec51..64cb63ea 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/validator/SequenceFlowValidator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/validator/SequenceFlowValidator.java @@ -17,7 +17,7 @@ public void checkIncoming(Map flowElementMap, FlowElement f List incomingList = flowElement.getIncoming(); if (incomingList.size() >1) { - throwElementValidatorException(flowElement, ErrorEnum.ELEMENT_TOO_MUCH_INCOMING); + throwElementValidatorException(flowElement, ErrorEnum.ELEMENT_TOO_MANY_INCOMING); } } @@ -27,7 +27,7 @@ public void checkOutgoing(Map flowElementMap, FlowElement f List outgoingList = flowElement.getOutgoing(); if (outgoingList.size() > 1) { - throwElementValidatorException(flowElement, ErrorEnum.ELEMENT_TOO_MUCH_OUTGOING); + throwElementValidatorException(flowElement, ErrorEnum.ELEMENT_TOO_MANY_OUTGOING); } } } diff --git a/engine/src/main/java/com/didiglobal/turbo/engine/validator/StartEventValidator.java b/engine/src/main/java/com/didiglobal/turbo/engine/validator/StartEventValidator.java index 02044a00..e5631d41 100644 --- a/engine/src/main/java/com/didiglobal/turbo/engine/validator/StartEventValidator.java +++ b/engine/src/main/java/com/didiglobal/turbo/engine/validator/StartEventValidator.java @@ -15,7 +15,7 @@ public class StartEventValidator extends ElementValidator { protected static final Logger LOGGER = LoggerFactory.getLogger(StartEventValidator.class); /** - * CheckIncoming: check userTask's incoming, warn while incoming is not empty. + * CheckIncoming: check startEvent's incoming, warn while incoming is not empty. * * @param flowElementMap, flowElement */ @@ -24,7 +24,7 @@ public void checkIncoming(Map flowElementMap, FlowElement f List incoming = flowElement.getIncoming(); if (CollectionUtils.isNotEmpty(incoming)) { - recordElementValidatorException(flowElement, ErrorEnum.ELEMENT_TOO_MUCH_INCOMING); + recordElementValidatorException(flowElement, ErrorEnum.ELEMENT_TOO_MANY_INCOMING); } } } diff --git a/engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator b/engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator new file mode 100644 index 00000000..b62c1691 --- /dev/null +++ b/engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator @@ -0,0 +1 @@ +com.didiglobal.turbo.engine.spi.calculator.GroovyExpressionCalculator \ No newline at end of file diff --git a/engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator b/engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator new file mode 100644 index 00000000..79bc031b --- /dev/null +++ b/engine/src/main/resources/META-INF/services/com.didiglobal.turbo.engine.spi.generator.IdGenerator @@ -0,0 +1 @@ +com.didiglobal.turbo.engine.spi.generator.StrongUuidGenerator \ No newline at end of file diff --git a/engine/src/main/resources/turbo.db.create/turbo.mysql.sql b/engine/src/main/resources/turbo.db.create/turbo.mysql.sql index ee95f522..07eff816 100644 --- a/engine/src/main/resources/turbo.db.create/turbo.mysql.sql +++ b/engine/src/main/resources/turbo.db.create/turbo.mysql.sql @@ -1,61 +1,68 @@ DROP TABLE IF EXISTS `em_flow_definition`; -CREATE TABLE IF NOT EXISTS `em_flow_definition` ( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', - `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', - `flow_name` varchar(64) NOT NULL DEFAULT '' COMMENT '流程名称', - `flow_key` varchar(32) NOT NULL DEFAULT '' COMMENT '流程业务标识', - `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', - `flow_model` mediumtext COMMENT '表单定义', - `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.初始态 2.编辑中 3.已下线)', - `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', - `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', - `operator` varchar(32) NOT NULL DEFAULT '' COMMENT '操作人', - `remark` varchar(512) NOT NULL DEFAULT '' COMMENT '备注', - `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', - `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', - `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', - PRIMARY KEY (`id`), - UNIQUE KEY `uniq_flow_module_id` (`flow_module_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='流程定义表'; +CREATE TABLE IF NOT EXISTS `em_flow_definition` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', + `flow_name` varchar(64) NOT NULL DEFAULT '' COMMENT '流程名称', + `flow_key` varchar(32) NOT NULL DEFAULT '' COMMENT '流程业务标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `flow_model` mediumtext COMMENT '表单定义', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.初始态 2.编辑中 3.已下线)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', + `operator` varchar(32) NOT NULL DEFAULT '' COMMENT '操作人', + `remark` varchar(512) NOT NULL DEFAULT '' COMMENT '备注', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_flow_module_id` (`flow_module_id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8 + ROW_FORMAT = COMPACT COMMENT ='流程定义表'; DROP TABLE IF EXISTS `em_flow_deployment`; -CREATE TABLE IF NOT EXISTS `em_flow_deployment` ( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', - `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', - `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', - `flow_name` varchar(64) NOT NULL DEFAULT '' COMMENT '流程名称', - `flow_key` varchar(32) NOT NULL DEFAULT '' COMMENT '流程业务标识', - `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', - `flow_model` mediumtext COMMENT '表单定义', - `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.已部署 3.已下线)', - `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', - `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', - `operator` varchar(32) NOT NULL DEFAULT '' COMMENT '操作人', - `remark` varchar(512) NOT NULL DEFAULT '' COMMENT '备注', - `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', - `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', - `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', - PRIMARY KEY (`id`), - UNIQUE KEY `uniq_flow_deploy_id` (`flow_deploy_id`), - KEY `idx_flow_module_id` (`flow_module_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='流程部署表'; +CREATE TABLE IF NOT EXISTS `em_flow_deployment` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', + `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', + `flow_name` varchar(64) NOT NULL DEFAULT '' COMMENT '流程名称', + `flow_key` varchar(32) NOT NULL DEFAULT '' COMMENT '流程业务标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `flow_model` mediumtext COMMENT '表单定义', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.已部署 3.已下线)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', + `operator` varchar(32) NOT NULL DEFAULT '' COMMENT '操作人', + `remark` varchar(512) NOT NULL DEFAULT '' COMMENT '备注', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_flow_deploy_id` (`flow_deploy_id`), + KEY `idx_flow_module_id` (`flow_module_id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8 + ROW_FORMAT = COMPACT COMMENT ='流程部署表'; DROP TABLE IF EXISTS `ei_flow_instance`; -CREATE TABLE IF NOT EXISTS `ei_flow_instance`( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', - `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', - `parent_flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '父流程执行实例id', - `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', - `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', - `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', - `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.执行完成 2.执行中 3.执行终止(强制终止))', - `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', - `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', - `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', - `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', - `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', - PRIMARY KEY (`id`), - UNIQUE KEY `uniq_flow_instance_id` (`flow_instance_id`) +CREATE TABLE IF NOT EXISTS `ei_flow_instance` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', + `parent_flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '父流程执行实例id', + `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', + `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.执行完成 2.执行中 3.执行终止(强制终止))', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_flow_instance_id` (`flow_instance_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8 ROW_FORMAT = COMPACT COMMENT ='流程执行实例表'; @@ -90,53 +97,62 @@ CREATE TABLE IF NOT EXISTS `ei_node_instance` `instance_data_id` varchar(128) NOT NULL DEFAULT '' COMMENT '实例数据id', `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', `node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '节点唯一标识', - `source_node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '上一个流程节点唯一标识', - `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', - `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.处理成功 2.处理中 3.处理失败 4.处理已撤销)', - `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', - `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', - `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', - `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', - `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', - PRIMARY KEY (`id`), - UNIQUE KEY `uniq_node_instance_id` (`node_instance_id`), - KEY `idx_fiid_sniid_nk` (`flow_instance_id`,`source_node_instance_id`,`node_key`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='节点执行实例表'; + `source_node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '上一个流程节点唯一标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.处理成功 2.处理中 3.处理失败 4.处理已撤销)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_node_instance_id` (`node_instance_id`), + KEY `idx_fiid_sniid_nk` (`flow_instance_id`, `source_node_instance_id`, `node_key`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8 + ROW_FORMAT = COMPACT COMMENT ='节点执行实例表'; DROP TABLE IF EXISTS `ei_node_instance_log`; -CREATE TABLE IF NOT EXISTS `ei_node_instance_log` ( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', - `node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '节点执行实例id', - `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', - `instance_data_id` varchar(128) NOT NULL DEFAULT '' COMMENT '实例数据id', - `node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '节点唯一标识', - `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', - `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '操作类型(1.系统执行 2.任务提交 3.任务撤销)', - `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.处理成功 2.处理中 3.处理失败 4.处理已撤销)', - `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', - `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', - `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', - `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='节点执行记录表'; +CREATE TABLE IF NOT EXISTS `ei_node_instance_log` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '节点执行实例id', + `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', + `instance_data_id` varchar(128) NOT NULL DEFAULT '' COMMENT '实例数据id', + `node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '节点唯一标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '操作类型(1.系统执行 2.任务提交 3.任务撤销)', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.处理成功 2.处理中 3.处理失败 4.处理已撤销)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8 + ROW_FORMAT = COMPACT COMMENT ='节点执行记录表'; DROP TABLE IF EXISTS `ei_instance_data`; -CREATE TABLE IF NOT EXISTS `ei_instance_data` ( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', - `node_instance_id` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '节点执行实例id', - `flow_instance_id` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '流程执行实例id', - `instance_data_id` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '实例数据id', - `flow_deploy_id` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '流程模型部署id', - `flow_module_id` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '流程模型id', - `node_key` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '节点唯一标识', - `tenant_id` varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '业务方标识', - `instance_data` longtext COLLATE utf8mb4_unicode_ci COMMENT '数据列表json', - `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '操作类型(1.实例初始化 2.系统执行 3.系统主动获取 4.上游更新 5.任务提交 6.任务撤回)', - `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', - `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', - `tenant` varchar(100) CHARACTER SET utf8 NOT NULL DEFAULT '' COMMENT '租户', - `caller` varchar(100) CHARACTER SET utf8 NOT NULL DEFAULT '' COMMENT '调用方', - PRIMARY KEY (`id`), - UNIQUE KEY `uniq_instance_data_id` (`instance_data_id`), - KEY `idx_flow_instance_id` (`flow_instance_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPACT COMMENT='实例数据表'; +CREATE TABLE IF NOT EXISTS `ei_instance_data` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `node_instance_id` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '节点执行实例id', + `flow_instance_id` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '流程执行实例id', + `instance_data_id` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '实例数据id', + `flow_deploy_id` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '流程模型部署id', + `flow_module_id` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '流程模型id', + `node_key` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '节点唯一标识', + `tenant_id` varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '业务方标识', + `instance_data` longtext COLLATE utf8mb4_unicode_ci COMMENT '数据列表json', + `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '操作类型(1.实例初始化 2.系统执行 3.系统主动获取 4.上游更新 5.任务提交 6.任务撤回)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) CHARACTER SET utf8 NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) CHARACTER SET utf8 NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_instance_data_id` (`instance_data_id`), + KEY `idx_flow_instance_id` (`flow_instance_id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_unicode_ci + ROW_FORMAT = COMPACT COMMENT ='实例数据表'; diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/dao/FlowDefinitionDAOTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/dao/FlowDefinitionDAOTest.java index d6291622..3f766a97 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/dao/FlowDefinitionDAOTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/dao/FlowDefinitionDAOTest.java @@ -7,9 +7,11 @@ import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import javax.annotation.Resource; + public class FlowDefinitionDAOTest extends BaseTest { - @Autowired + @Resource private FlowDefinitionDAO flowDefinitionDAO; @Test @@ -18,7 +20,7 @@ public void insertTest() { flowDefinitionPO.setFlowModuleId("testFlowModuleId_" + System.currentTimeMillis()); int result = flowDefinitionDAO.insert(flowDefinitionPO); LOGGER.info("insertTest.result={}", result); - Assert.assertTrue(result == 1); + Assert.assertEquals(1, result); } @Test @@ -26,10 +28,10 @@ public void updateByModuleIdTest() { FlowDefinitionPO flowDefinitionPO = EntityBuilder.buildFlowDefinitionPO(); flowDefinitionPO.setFlowModuleId("testFlowModuleId_" + System.currentTimeMillis()); int insertResult = flowDefinitionDAO.insert(flowDefinitionPO); - Assert.assertTrue(insertResult == 1); + Assert.assertEquals(1, insertResult); int updateResult = flowDefinitionDAO.updateByModuleId(flowDefinitionPO); LOGGER.info("updateByModuleIdTest.||result={}", updateResult); - Assert.assertTrue(updateResult == 1); + Assert.assertEquals(1, updateResult); } @Test @@ -37,10 +39,10 @@ public void selectByModuleIdTest() { FlowDefinitionPO flowDefinitionPO = EntityBuilder.buildFlowDefinitionPO(); flowDefinitionPO.setFlowModuleId("testFlowModuleId_" + System.currentTimeMillis()); int result = flowDefinitionDAO.insert(flowDefinitionPO); - Assert.assertTrue(result == 1); + Assert.assertEquals(1, result); String flowModuleId = flowDefinitionPO.getFlowModuleId(); FlowDefinitionPO queryFlowDefinitionPO = flowDefinitionDAO.selectByModuleId(flowDefinitionPO.getFlowModuleId()); LOGGER.info("selectByModuleIdTest.||flowDefinitionPO={}", flowDefinitionPO); - Assert.assertTrue(flowModuleId.equals(queryFlowDefinitionPO.getFlowModuleId())); + Assert.assertEquals(flowModuleId, queryFlowDefinitionPO.getFlowModuleId()); } } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/dao/NodeInstanceDAOTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/dao/NodeInstanceDAOTest.java index 10b19f4f..981ba583 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/dao/NodeInstanceDAOTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/dao/NodeInstanceDAOTest.java @@ -18,14 +18,14 @@ public class NodeInstanceDAOTest extends BaseTest { @Test public void insert(){ - NodeInstancePO nodeInstancePO = EntityBuilder.buildNodeInstancePO(); + NodeInstancePO nodeInstancePO = EntityBuilder.buildDynamicNodeInstancePO(); int result = nodeInstanceDAO.insert(nodeInstancePO); - Assert.assertTrue(result == 1); + Assert.assertEquals(1, result); } @Test public void insertOrUpdateList(){ - NodeInstancePO nodeInstancePO = EntityBuilder.buildNodeInstancePO(); + NodeInstancePO nodeInstancePO = EntityBuilder.buildDynamicNodeInstancePO(); nodeInstanceDAO.insert(nodeInstancePO); nodeInstancePO = nodeInstanceDAO.selectByNodeInstanceId(nodeInstancePO.getFlowInstanceId(), nodeInstancePO.getNodeInstanceId()); List nodeInstancePOList = new ArrayList<>(); @@ -38,11 +38,11 @@ public void insertOrUpdateList(){ @Test public void updateStatus() { - NodeInstancePO nodeInstancePO = EntityBuilder.buildNodeInstancePO(); + NodeInstancePO nodeInstancePO = EntityBuilder.buildDynamicNodeInstancePO(); nodeInstanceDAO.insert(nodeInstancePO); nodeInstanceDAO.updateStatus(nodeInstancePO, NodeInstanceStatus.COMPLETED); NodeInstancePO result = nodeInstanceDAO.selectByNodeInstanceId(nodeInstancePO.getFlowInstanceId(), nodeInstancePO.getNodeInstanceId()); - Assert.assertTrue(result.getStatus() == NodeInstanceStatus.COMPLETED); + Assert.assertEquals(NodeInstanceStatus.COMPLETED, (int) result.getStatus()); } } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/FlowDefinitionMapperTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/FlowDefinitionMapperTest.java index 2c91fc98..d8624858 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/FlowDefinitionMapperTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/FlowDefinitionMapperTest.java @@ -5,11 +5,12 @@ import com.didiglobal.turbo.engine.util.EntityBuilder; import org.junit.Assert; import org.junit.Test; -import org.springframework.beans.factory.annotation.Autowired; + +import javax.annotation.Resource; public class FlowDefinitionMapperTest extends BaseTest { - @Autowired + @Resource private FlowDefinitionMapper flowDefinitionMapper; @Test @@ -17,7 +18,7 @@ public void insert() { FlowDefinitionPO flowDefinitionPO = EntityBuilder.buildFlowDefinitionPO(); flowDefinitionPO.setFlowModuleId("testFlowModuleId_" + System.currentTimeMillis()); int result = flowDefinitionMapper.insert(flowDefinitionPO); - Assert.assertTrue(result == 1); + Assert.assertEquals(1, result); } @Test @@ -28,9 +29,9 @@ public void update() { flowDefinitionPO = flowDefinitionMapper.selectByFlowModuleId(flowDefinitionPO.getFlowModuleId()); flowDefinitionPO.setStatus(3); int result = flowDefinitionMapper.updateById(flowDefinitionPO); - Assert.assertTrue(result == 1); + Assert.assertEquals(1, result); flowDefinitionPO = flowDefinitionMapper.selectByFlowModuleId(flowDefinitionPO.getFlowModuleId()); - Assert.assertTrue(flowDefinitionPO.getStatus().equals(3)); + Assert.assertEquals(3, (int) flowDefinitionPO.getStatus()); } @Test @@ -38,11 +39,11 @@ public void selectByFlowModuleId() { FlowDefinitionPO flowDefinitionPO = EntityBuilder.buildFlowDefinitionPO(); flowDefinitionPO.setFlowModuleId("testFlowModuleId_" + System.currentTimeMillis()); int result = flowDefinitionMapper.insert(flowDefinitionPO); - Assert.assertTrue(result == 1); + Assert.assertEquals(1, result); String flowModuleId = flowDefinitionPO.getFlowModuleId(); FlowDefinitionPO queryFlowDefinitionPO = flowDefinitionMapper.selectByFlowModuleId(flowModuleId); LOGGER.info("selectByModuleIdTest.||flowDefinitionPO={}", flowDefinitionPO); - Assert.assertTrue(flowModuleId.equals(queryFlowDefinitionPO.getFlowModuleId())); + Assert.assertEquals(flowModuleId, queryFlowDefinitionPO.getFlowModuleId()); } } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/FlowDeploymentMapperTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/FlowDeploymentMapperTest.java index 9c43f7da..6d244ef2 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/FlowDeploymentMapperTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/FlowDeploymentMapperTest.java @@ -8,9 +8,11 @@ import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import javax.annotation.Resource; + public class FlowDeploymentMapperTest extends BaseTest { - @Autowired + @Resource private FlowDeploymentMapper flowDeploymentMapper; @Test @@ -18,7 +20,7 @@ public void insert() { FlowDeploymentPO flowDeploymentPO = EntityBuilder.buildFlowDeploymentPO(); flowDeploymentPO.setFlowDeployId("testFlowDeployId_" + System.currentTimeMillis()); int result = flowDeploymentMapper.insert(flowDeploymentPO); - Assert.assertTrue(result == 1); + Assert.assertEquals(1, result); } @Test @@ -29,7 +31,7 @@ public void selectByDeployId() { flowDeploymentMapper.insert(flowDeploymentPO); String flowDeployId = flowDeploymentPO.getFlowDeployId(); flowDeploymentPO = flowDeploymentMapper.selectByDeployId(flowDeployId); - Assert.assertTrue(flowDeployId.equals(flowDeploymentPO.getFlowDeployId())); + Assert.assertEquals(flowDeployId, flowDeploymentPO.getFlowDeployId()); } @Test @@ -45,6 +47,6 @@ public void selectByModuleId() { flowDeploymentPO.setFlowDeployId("testFlowDeployId_" + System.currentTimeMillis()); flowDeploymentMapper.insert(flowDeploymentPONew); FlowDeploymentPO flowDeploymentPORes = flowDeploymentMapper.selectByModuleId(flowModuleId1); - Assert.assertTrue(flowDeploymentPONew.getFlowDeployId().equals(flowDeploymentPORes.getFlowDeployId())); + Assert.assertEquals(flowDeploymentPONew.getFlowDeployId(), flowDeploymentPORes.getFlowDeployId()); } } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/InstanceDataMapperTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/InstanceDataMapperTest.java index 7071d2b0..e78329c1 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/InstanceDataMapperTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/dao/mapper/InstanceDataMapperTest.java @@ -7,9 +7,11 @@ import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import javax.annotation.Resource; + public class InstanceDataMapperTest extends BaseTest { - @Autowired + @Resource private InstanceDataMapper instanceDataMapper; @Test @@ -17,7 +19,7 @@ public void insert() { InstanceDataPO instanceDataPO = EntityBuilder.buildDynamicInstanceDataPO(); int result = instanceDataMapper.insert(instanceDataPO); LOGGER.info("insert.result={}", result); - Assert.assertTrue(result == 1); + Assert.assertEquals(1, result); } @Test @@ -25,7 +27,7 @@ public void select() { InstanceDataPO instanceDataPO = EntityBuilder.buildDynamicInstanceDataPO(); instanceDataMapper.insert(instanceDataPO); InstanceDataPO result = instanceDataMapper.select(instanceDataPO.getFlowInstanceId(), instanceDataPO.getInstanceDataId()); - Assert.assertTrue(result.getInstanceDataId().equals(instanceDataPO.getInstanceDataId())); + Assert.assertEquals(result.getInstanceDataId(), instanceDataPO.getInstanceDataId()); } @Test @@ -35,6 +37,6 @@ public void selectRecentOne() { InstanceDataPO newInstanceDataPO = EntityBuilder.buildDynamicInstanceDataPO(); instanceDataMapper.insert(newInstanceDataPO); InstanceDataPO result = instanceDataMapper.selectRecentOne(oldInstanceDataPO.getFlowInstanceId()); - Assert.assertTrue(result.getInstanceDataId().equals(newInstanceDataPO.getInstanceDataId())); + Assert.assertEquals(result.getInstanceDataId(), newInstanceDataPO.getInstanceDataId()); } } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/engine/ProcessEngineTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/engine/ProcessEngineTest.java index ad6e9484..60e8027a 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/engine/ProcessEngineTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/engine/ProcessEngineTest.java @@ -16,11 +16,8 @@ public class ProcessEngineTest extends BaseTest { - @Autowired - ProcessEngine processEngine; - @Resource - ProcessEngineImpl processEngineImpl; + private ProcessEngineImpl processEngineImpl; @Test public void createFlowTest() { diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/processor/RuntimeProcessorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/processor/RuntimeProcessorTest.java index 8758309c..70386c5e 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/processor/RuntimeProcessorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/processor/RuntimeProcessorTest.java @@ -29,7 +29,7 @@ public class RuntimeProcessorTest extends BaseTest { @Resource private FlowDeploymentMapper flowDeploymentMapper; - private StartProcessResult startProcess() throws Exception { + private StartProcessResult startProcess() { // prepare FlowDeploymentPO flowDeploymentPO = EntityBuilder.buildSpecialFlowDeploymentPO(); FlowDeploymentPO _flowDeploymentPO = flowDeploymentMapper.selectByDeployId(flowDeploymentPO.getFlowDeployId()); @@ -54,15 +54,15 @@ private StartProcessResult startProcess() throws Exception { } @Test - public void testStartProcess() throws Exception { + public void testStartProcess() { StartProcessResult startProcessResult = startProcess(); - Assert.assertTrue(startProcessResult.getErrCode() == ErrorEnum.COMMIT_SUSPEND.getErrNo()); + Assert.assertEquals(startProcessResult.getErrCode(), ErrorEnum.COMMIT_SUSPEND.getErrNo()); Assert.assertTrue(StringUtils.equals(startProcessResult.getActiveTaskInstance().getModelKey(), "BranchUserTask_0scrl8d")); } // UserTask -> EndEvent @Test - public void testNormalCommitToEnd() throws Exception { + public void testNormalCommitToEnd() { StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); @@ -74,13 +74,13 @@ public void testNormalCommitToEnd() throws Exception { CommitTaskResult commitTaskResult = runtimeProcessor.commit(commitTaskParam); LOGGER.info("testCommit.||commitTaskResult={}", commitTaskResult); - Assert.assertTrue(commitTaskResult.getErrCode() == ErrorEnum.SUCCESS.getErrNo()); + Assert.assertEquals(commitTaskResult.getErrCode(), ErrorEnum.SUCCESS.getErrNo()); Assert.assertTrue(StringUtils.equals(commitTaskResult.getActiveTaskInstance().getModelKey(), "EndEvent_0s4vsxw")); } // UserTask -> ExclusiveGateway -> UserTask @Test - public void testNormalCommitToUserTask() throws Exception { + public void testNormalCommitToUserTask() { StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); @@ -92,14 +92,14 @@ public void testNormalCommitToUserTask() throws Exception { CommitTaskResult commitTaskResult = runtimeProcessor.commit(commitTaskParam); LOGGER.info("testCommit.||commitTaskResult={}", commitTaskResult); - Assert.assertTrue(commitTaskResult.getErrCode() == ErrorEnum.COMMIT_SUSPEND.getErrNo()); + Assert.assertEquals(commitTaskResult.getErrCode(), ErrorEnum.COMMIT_SUSPEND.getErrNo()); Assert.assertTrue(StringUtils.equals(commitTaskResult.getActiveTaskInstance().getModelKey(), "UserTask_0uld0u9")); } // UserTask -> ExclusiveGateway -> UserTask // UserTask -> @Test - public void testRepeatedCommitToUserTask() throws Exception { + public void testRepeatedCommitToUserTask() { StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); @@ -108,18 +108,19 @@ public void testRepeatedCommitToUserTask() throws Exception { List variables = new ArrayList<>(); variables.add(new InstanceData("danxuankuang_ytgyk", 0)); commitTaskParam.setVariables(variables); + // first commit + runtimeProcessor.commit(commitTaskParam); + // commit again CommitTaskResult commitTaskResult = runtimeProcessor.commit(commitTaskParam); - - commitTaskResult = runtimeProcessor.commit(commitTaskParam); LOGGER.info("testCommit.||commitTaskResult={}", commitTaskResult); - Assert.assertTrue(commitTaskResult.getErrCode() == ErrorEnum.COMMIT_SUSPEND.getErrNo()); + Assert.assertEquals(commitTaskResult.getErrCode(), ErrorEnum.COMMIT_SUSPEND.getErrNo()); Assert.assertTrue(StringUtils.equals(commitTaskResult.getActiveTaskInstance().getModelKey(), "UserTask_0uld0u9")); } // UserTask -> EndEvent -> Commit again @Test - public void testCommitCompletedFlowInstance() throws Exception { + public void testCommitCompletedFlowInstance() { StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); @@ -128,16 +129,17 @@ public void testCommitCompletedFlowInstance() throws Exception { List variables = new ArrayList<>(); variables.add(new InstanceData("danxuankuang_ytgyk", 1)); commitTaskParam.setVariables(variables); + // first commit + runtimeProcessor.commit(commitTaskParam); + // commit again CommitTaskResult commitTaskResult = runtimeProcessor.commit(commitTaskParam); - - commitTaskResult = runtimeProcessor.commit(commitTaskParam); LOGGER.info("testCommit.||commitTaskResult={}", commitTaskResult); - Assert.assertTrue(commitTaskResult.getErrCode() == ErrorEnum.REENTRANT_WARNING.getErrNo()); + Assert.assertEquals(commitTaskResult.getErrCode(), ErrorEnum.REENTRANT_WARNING.getErrNo()); } @Test - public void testCommitTerminatedFlowInstance() throws Exception { + public void testCommitTerminatedFlowInstance() { StartProcessResult startProcessResult = startProcess(); runtimeProcessor.terminateProcess(startProcessResult.getFlowInstanceId(), false); @@ -150,12 +152,12 @@ public void testCommitTerminatedFlowInstance() throws Exception { commitTaskParam.setVariables(variables); CommitTaskResult commitTaskResult = runtimeProcessor.commit(commitTaskParam); - Assert.assertTrue(commitTaskResult.getErrCode() == ErrorEnum.COMMIT_REJECTRD.getErrNo()); + Assert.assertEquals(commitTaskResult.getErrCode(), ErrorEnum.COMMIT_REJECTED.getErrNo()); } // UserTask <- ExclusiveGateway <- UserTask : Commit old UserTask @Test - public void testRollbackToUserTaskAndCommitOldUserTask() throws Exception { + public void testRollbackToUserTaskAndCommitOldUserTask() { // start process StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); @@ -178,12 +180,12 @@ public void testRollbackToUserTaskAndCommitOldUserTask() throws Exception { commitTaskResult = runtimeProcessor.commit(commitTaskParam); LOGGER.info("testRollbackToUserTaskAndCommitOldUserTask.||commitTaskResult={}", commitTaskResult); - Assert.assertTrue(commitTaskResult.getErrCode() == ErrorEnum.COMMIT_FAILED.getErrNo()); + Assert.assertEquals(commitTaskResult.getErrCode(), ErrorEnum.COMMIT_FAILED.getErrNo()); Assert.assertTrue(StringUtils.equals(commitTaskResult.getActiveTaskInstance().getModelKey(), "BranchUserTask_0scrl8d")); } @Test - public void testRollbackFromMiddleUserTask() throws Exception { + public void testRollbackFromMiddleUserTask() { // start process StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); @@ -206,15 +208,14 @@ public void testRollbackFromMiddleUserTask() throws Exception { // Ignore current userTask LOGGER.info("testRollbackFromMiddleUserTask.||rollbackTaskResult={}", rollbackTaskResult); - Assert.assertTrue(rollbackTaskResult.getErrCode() == ErrorEnum.ROLLBACK_SUSPEND.getErrNo()); - Assert.assertTrue(StringUtils.equals(rollbackTaskResult.getActiveTaskInstance().getModelKey(), "BranchUserTask_0scrl8d")); + Assert.assertEquals(rollbackTaskResult.getErrCode(), ErrorEnum.ROLLBACK_SUSPEND.getErrNo()); + Assert.assertEquals("BranchUserTask_0scrl8d", rollbackTaskResult.getActiveTaskInstance().getModelKey()); } - // UserTask <- ExclusiveGateway <- UserTask @Test - public void testRollbackToUserTask() throws Exception { + public void testRollbackToUserTask() { // start process StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); @@ -234,13 +235,13 @@ public void testRollbackToUserTask() throws Exception { RollbackTaskResult rollbackTaskResult = runtimeProcessor.rollback(rollbackTaskParam); LOGGER.info("testRollback.||rollbackTaskResult={}", rollbackTaskResult); - Assert.assertTrue(rollbackTaskResult.getErrCode() == ErrorEnum.ROLLBACK_SUSPEND.getErrNo()); - Assert.assertTrue(StringUtils.equals(rollbackTaskResult.getActiveTaskInstance().getModelKey(), "BranchUserTask_0scrl8d")); + Assert.assertEquals(rollbackTaskResult.getErrCode(), ErrorEnum.ROLLBACK_SUSPEND.getErrNo()); + Assert.assertEquals("BranchUserTask_0scrl8d", rollbackTaskResult.getActiveTaskInstance().getModelKey()); } // StartEvent <- UserTask @Test - public void testRollbackToStartEvent() throws Exception { + public void testRollbackToStartEvent() { // start process StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); @@ -265,12 +266,12 @@ public void testRollbackToStartEvent() throws Exception { rollbackTaskParam.setTaskInstanceId(rollbackTaskResult.getActiveTaskInstance().getNodeInstanceId()); rollbackTaskResult = runtimeProcessor.rollback(rollbackTaskParam); LOGGER.info("testRollback.||rollbackTaskResult={}", rollbackTaskResult); - Assert.assertTrue(rollbackTaskResult.getErrCode() == ErrorEnum.NO_USER_TASK_TO_ROLLBACK.getErrNo()); + Assert.assertEquals(rollbackTaskResult.getErrCode(), ErrorEnum.NO_USER_TASK_TO_ROLLBACK.getErrNo()); } // rollback completed process @Test - public void testRollbackFromEndEvent() throws Exception { + public void testRollbackFromEndEvent() { // start process StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); @@ -290,19 +291,19 @@ public void testRollbackFromEndEvent() throws Exception { RollbackTaskResult rollbackTaskResult = runtimeProcessor.rollback(rollbackTaskParam); LOGGER.info("testRollback.||rollbackTaskResult={}", rollbackTaskResult); - Assert.assertTrue(rollbackTaskResult.getErrCode() == ErrorEnum.ROLLBACK_REJECTRD.getErrNo()); + Assert.assertEquals(rollbackTaskResult.getErrCode(), ErrorEnum.ROLLBACK_REJECTED.getErrNo()); } @Test - public void testTerminateProcess() throws Exception { + public void testTerminateProcess() { StartProcessResult startProcessResult = startProcess(); TerminateResult terminateResult = runtimeProcessor.terminateProcess(startProcessResult.getFlowInstanceId(), false); LOGGER.info("testTerminateProcess.||terminateResult={}", terminateResult); - Assert.assertTrue(terminateResult.getErrCode() == ErrorEnum.SUCCESS.getErrNo()); + Assert.assertEquals(terminateResult.getErrCode(), ErrorEnum.SUCCESS.getErrNo()); } @Test - public void testGetHistoryUserTaskList() throws Exception { + public void testGetHistoryUserTaskList() { StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); commitTaskParam.setFlowInstanceId(startProcessResult.getFlowInstanceId()); @@ -324,15 +325,14 @@ public void testGetHistoryUserTaskList() throws Exception { sb.append(elementInstanceResult.getStatus()); sb.append("]->"); } - LOGGER.info("testGetHistoryUserTaskList.||snapshot={}", sb.toString()); + LOGGER.info("testGetHistoryUserTaskList.||snapshot={}", sb); - Assert.assertTrue(nodeInstanceListResult.getNodeInstanceList().size() == 2); - Assert.assertTrue(StringUtils.equals(nodeInstanceListResult.getNodeInstanceList().get(0).getModelKey(), "UserTask_0uld0u9")); + Assert.assertEquals(2, nodeInstanceListResult.getNodeInstanceList().size()); + Assert.assertEquals("UserTask_0uld0u9", nodeInstanceListResult.getNodeInstanceList().get(0).getModelKey()); } - @Test - public void testGetFailedHistoryElementList() throws Exception { + public void testGetFailedHistoryElementList() { StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); commitTaskParam.setFlowInstanceId(startProcessResult.getFlowInstanceId()); @@ -345,7 +345,7 @@ public void testGetFailedHistoryElementList() throws Exception { // UserTask -> ExclusiveGateway : Failed CommitTaskResult commitTaskResult = runtimeProcessor.commit(commitTaskParam); LOGGER.info("testGetFailedHistoryElementList.||commitTaskResult={}", commitTaskResult); - Assert.assertTrue(commitTaskResult.getErrCode() == ErrorEnum.GET_OUTGOING_FAILED.getErrNo()); + Assert.assertEquals(commitTaskResult.getErrCode(), ErrorEnum.GET_OUTGOING_FAILED.getErrNo()); ElementInstanceListResult elementInstanceListResult = runtimeProcessor.getHistoryElementList(commitTaskResult.getFlowInstanceId(), false); LOGGER.info("testGetHistoryElementList.||elementInstanceListResult={}", elementInstanceListResult); @@ -357,14 +357,14 @@ public void testGetFailedHistoryElementList() throws Exception { sb.append(elementInstanceResult.getStatus()); sb.append("]->"); } - LOGGER.info("testGetHistoryElementList.||snapshot={}", sb.toString()); + LOGGER.info("testGetHistoryElementList.||snapshot={}", sb); - Assert.assertTrue(elementInstanceListResult.getElementInstanceList().size() == 5); - Assert.assertTrue(StringUtils.equals(elementInstanceListResult.getElementInstanceList().get(4).getModelKey(), "ExclusiveGateway_0yq2l0s")); + Assert.assertEquals(5, elementInstanceListResult.getElementInstanceList().size()); + Assert.assertEquals("ExclusiveGateway_0yq2l0s", elementInstanceListResult.getElementInstanceList().get(4).getModelKey()); } @Test - public void testGetCompletedHistoryElementList() throws Exception { + public void testGetCompletedHistoryElementList() { StartProcessResult startProcessResult = startProcess(); CommitTaskParam commitTaskParam = new CommitTaskParam(); commitTaskParam.setFlowInstanceId(startProcessResult.getFlowInstanceId()); @@ -386,15 +386,15 @@ public void testGetCompletedHistoryElementList() throws Exception { sb.append(elementInstanceResult.getStatus()); sb.append("]->"); } - LOGGER.info("testGetHistoryElementList.||snapshot={}", sb.toString()); + LOGGER.info("testGetHistoryElementList.||snapshot={}", sb); - Assert.assertTrue(elementInstanceListResult.getElementInstanceList().size() == 5); - Assert.assertTrue(StringUtils.equals(elementInstanceListResult.getElementInstanceList().get(4).getModelKey(), "EndEvent_0s4vsxw")); + Assert.assertEquals(5, elementInstanceListResult.getElementInstanceList().size()); + Assert.assertEquals("EndEvent_0s4vsxw", elementInstanceListResult.getElementInstanceList().get(4).getModelKey()); } @Test - public void testGetInstanceData() throws Exception { + public void testGetInstanceData() { StartProcessResult startProcessResult = startProcess(); String flowInstanceId = startProcessResult.getFlowInstanceId(); InstanceDataListResult instanceDataList = runtimeProcessor.getInstanceData(flowInstanceId, false); @@ -442,16 +442,16 @@ public void testGetInstanceData() throws Exception { LOGGER.info("testGetInstanceData 5.||instanceDataList={}", instanceDataList); String initData = JSON.toJSONString(startProcessResult.getVariables()); String rollbackData = JSON.toJSONString(rollbackTaskResult1.getVariables()); - Assert.assertTrue(StringUtils.equals(initData, rollbackData)); + Assert.assertEquals(initData, rollbackData); } @Test - public void testGetNodeInstance() throws Exception { + public void testGetNodeInstance() { StartProcessResult startProcessResult = startProcess(); String flowInstanceId = startProcessResult.getFlowInstanceId(); NodeInstanceResult nodeInstanceResult = runtimeProcessor.getNodeInstance(flowInstanceId, startProcessResult.getActiveTaskInstance().getNodeInstanceId(), false); LOGGER.info("testGetNodeInstance.||nodeInstanceResult={}", nodeInstanceResult); - Assert.assertTrue(StringUtils.equals(nodeInstanceResult.getNodeInstance().getNodeInstanceId(), startProcessResult.getActiveTaskInstance().getNodeInstanceId())); + Assert.assertEquals(startProcessResult.getActiveTaskInstance().getNodeInstanceId(), nodeInstanceResult.getNodeInstance().getNodeInstanceId()); } } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/runner/BaseTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/runner/BaseTest.java index 7697ef65..b1773e77 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/runner/BaseTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/runner/BaseTest.java @@ -1,5 +1,6 @@ package com.didiglobal.turbo.engine.runner; +import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -11,4 +12,7 @@ public class BaseTest { protected static final Logger LOGGER = LoggerFactory.getLogger(BaseTest.class); + + @Test + public void test(){} } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/runner/TestEngineApplication.java b/engine/src/test/java/com/didiglobal/turbo/engine/runner/TestEngineApplication.java index 123add85..1f53ff1c 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/runner/TestEngineApplication.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/runner/TestEngineApplication.java @@ -1,16 +1,15 @@ package com.didiglobal.turbo.engine.runner; import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; +import com.didiglobal.turbo.engine.annotation.EnableTurboEngine; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; -@SpringBootApplication -@EnableAutoConfiguration(exclude = {DruidDataSourceAutoConfigure.class}) -@ComponentScan("com.didiglobal.turbo.engine") -@MapperScan(basePackages = {"com.didiglobal.turbo.engine.dao"}) +@EnableTurboEngine +@SpringBootApplication(scanBasePackages = "com.didiglobal.turbo.engine", exclude = {DruidDataSourceAutoConfigure.class}) public class TestEngineApplication { public static void main(String[] args) { SpringApplication.run(TestEngineApplication.class, args); diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/TurboServiceLoaderTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/TurboServiceLoaderTest.java new file mode 100644 index 00000000..f1ccbed3 --- /dev/null +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/TurboServiceLoaderTest.java @@ -0,0 +1,23 @@ +package com.didiglobal.turbo.engine.spi; + +import com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator; +import com.didiglobal.turbo.engine.spi.generator.IdGenerator; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Collection; + +public class TurboServiceLoaderTest { + + @Test + public void assertExpressionCalculatorExists(){ + Collection serviceInterfaces = TurboServiceLoader.getServiceInterfaces(ExpressionCalculator.class); + Assert.assertTrue(serviceInterfaces.size() > 0); + } + + @Test + public void assertIdGeneratorExists(){ + Collection serviceInterfaces = TurboServiceLoader.getServiceInterfaces(IdGenerator.class); + Assert.assertTrue(serviceInterfaces.size() > 0); + } +} diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactoryTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactoryTest.java new file mode 100644 index 00000000..0e42135d --- /dev/null +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/ExpressionCalculatorFactoryTest.java @@ -0,0 +1,37 @@ +package com.didiglobal.turbo.engine.spi.calculator; + +import org.junit.Assert; +import org.junit.Test; + +public class ExpressionCalculatorFactoryTest { + + @Test + public void assertGroovyExpressionCalculatorExists() { + Assert.assertTrue(ExpressionCalculatorFactory.contains("groovy")); + Assert.assertTrue(ExpressionCalculatorFactory.contains("pattern")); + Assert.assertTrue(ExpressionCalculatorFactory.contains("test")); + } + + @Test + public void assertNotExists() { + Assert.assertFalse(ExpressionCalculatorFactory.contains("Tn3UI7")); + } + + @Test + public void assertExpressionCalculatorExistsWithNoType() { + ExpressionCalculator defaultExpressionCalculator = ExpressionCalculatorFactory.getExpressionCalculator(""); + Assert.assertNotNull(defaultExpressionCalculator); + } + + @Test + public void assertDefaultExpressionCalculatorNotGroovy() { + ExpressionCalculator defaultExpressionCalculator = ExpressionCalculatorFactory.getExpressionCalculator(""); + Assert.assertFalse(defaultExpressionCalculator instanceof GroovyExpressionCalculator); + } + + @Test + public void assertDefaultExpressionCalculatorIsTest() { + ExpressionCalculator defaultExpressionCalculator = ExpressionCalculatorFactory.getExpressionCalculator(""); + Assert.assertTrue(defaultExpressionCalculator instanceof TestExpressionCalculator); + } +} diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/GroovyExpressionCalculatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/GroovyExpressionCalculatorTest.java new file mode 100644 index 00000000..2aa82e76 --- /dev/null +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/GroovyExpressionCalculatorTest.java @@ -0,0 +1,60 @@ +package com.didiglobal.turbo.engine.spi.calculator; + +import com.didiglobal.turbo.engine.exception.ProcessException; +import com.google.common.collect.Maps; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class GroovyExpressionCalculatorTest { + + @Test + public void testCompare(){ + String expression = "${key_long < key_int}"; + Assert.assertFalse(ExpressionCalculatorFactory.getExpressionCalculator("groovy").calculate(expression, getData())); + } + + @Test + public void testCalculate(){ + String expression = "${key_long + key_int == 223}"; + Assert.assertTrue(ExpressionCalculatorFactory.getExpressionCalculator("groovy").calculate(expression, getData())); + } + + @Test + public void testList(){ + String expression = "key_list.contains(1)"; + Assert.assertTrue(ExpressionCalculatorFactory.getExpressionCalculator("groovy").calculate(expression, getData())); + } + + @Test + public void testNoSuchProperty(){ + String expression = "key_none.contains(1)"; + Boolean result = false; + try { + result = ExpressionCalculatorFactory.getExpressionCalculator("groovy").calculate(expression, getData()); + } catch (ProcessException e) { + // do nothing + } + Assert.assertFalse(result); + } + + + public Map getData(){ + Map data = Maps.newHashMap(); + data.put("key_string", "test string"); + data.put("key_long", 123L); + data.put("key_int", 100); + data.put("key_double", 10.1d); + data.put("key_float", 20.2); + data.put("key_boolean", false); + data.put("key_list", getList()); + return data; + } + + private List getList() { + return Arrays.asList(1,2,3,4,5); + } +} diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/PatternExpressionCalculator.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/PatternExpressionCalculator.java new file mode 100644 index 00000000..bbd3ab02 --- /dev/null +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/PatternExpressionCalculator.java @@ -0,0 +1,26 @@ +package com.didiglobal.turbo.engine.spi.calculator; + +import com.didiglobal.turbo.engine.exception.ProcessException; +import com.didiglobal.turbo.engine.spi.SPIOrder; + +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * test pattern calculator + */ +public class PatternExpressionCalculator implements ExpressionCalculator { + + @Override + public String getType() { + return "pattern"; + } + + @Override + public Boolean calculate(String expression, Map dataMap) throws ProcessException { + Pattern compile = Pattern.compile(expression); + Matcher data = compile.matcher((String) dataMap.get("data")); + return data.matches(); + } +} diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/TestExpressionCalculator.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/TestExpressionCalculator.java new file mode 100644 index 00000000..3f6edba5 --- /dev/null +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/calculator/TestExpressionCalculator.java @@ -0,0 +1,28 @@ +package com.didiglobal.turbo.engine.spi.calculator; + +import com.didiglobal.turbo.engine.exception.ProcessException; +import com.didiglobal.turbo.engine.spi.SPIOrder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; + +/** + * test calculator + */ +@SPIOrder(0) +public class TestExpressionCalculator implements ExpressionCalculator { + + private static final Logger LOGGER = LoggerFactory.getLogger(TestExpressionCalculator.class); + + @Override + public String getType() { + return "test"; + } + + @Override + public Boolean calculate(String expression, Map dataMap) throws ProcessException { + LOGGER.info("enter TestExpressionCalculator, but use groovy for test"); + return ExpressionCalculatorFactory.getExpressionCalculator("groovy").calculate(expression, dataMap); + } +} diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactoryTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactoryTest.java new file mode 100644 index 00000000..b7b1995e --- /dev/null +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/generator/IdGenerateFactoryTest.java @@ -0,0 +1,16 @@ +package com.didiglobal.turbo.engine.spi.generator; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; + +public class IdGenerateFactoryTest { + + @Test + public void assertExists() { + IdGenerator idGenerator = IdGenerateFactory.getIdGenerator(); + Assert.assertNotNull(idGenerator); + Assert.assertTrue(StringUtils.isNotBlank(idGenerator.getNextId())); + } + +} diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/spi/generator/StrongUuidGeneratorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/spi/generator/StrongUuidGeneratorTest.java new file mode 100644 index 00000000..20767b5a --- /dev/null +++ b/engine/src/test/java/com/didiglobal/turbo/engine/spi/generator/StrongUuidGeneratorTest.java @@ -0,0 +1,26 @@ +package com.didiglobal.turbo.engine.spi.generator; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class StrongUuidGeneratorTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(StrongUuidGeneratorTest.class); + + private final IdGenerator idGenerator = IdGenerateFactory.getIdGenerator(); + + @Test + public void testDoExecute() { + int count = 1000; + long start = System.currentTimeMillis(); + for (int i = 0; i < count; i++) { + String nextId = idGenerator.getNextId(); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug(nextId); + } + } + + LOGGER.info("generate {} ids, cost {}ms", count, System.currentTimeMillis() - start); + } +} diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/util/EntityBuilder.java b/engine/src/test/java/com/didiglobal/turbo/engine/util/EntityBuilder.java index 42ce7f1e..8d3f04a0 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/util/EntityBuilder.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/util/EntityBuilder.java @@ -386,7 +386,7 @@ public static FlowInstancePO buildFlowInstancePO() { public static FlowInstancePO buildDynamicFlowInstancePO() { FlowInstancePO flowInstancePO = EntityBuilder.buildFlowInstancePO(); - flowInstancePO.setFlowInstanceId("testFlowInstanceId_" + System.currentTimeMillis() + new Random().nextInt()); + flowInstancePO.setFlowInstanceId("testFlowInstanceId_" + UUID.randomUUID()); return flowInstancePO; } @@ -409,8 +409,8 @@ public static NodeInstancePO buildNodeInstancePO() { public static NodeInstancePO buildDynamicNodeInstancePO() { NodeInstancePO nodeInstancePO = buildNodeInstancePO(); - nodeInstancePO.setNodeInstanceId("testNodeInstanceId_" + UUID.randomUUID().toString()); - nodeInstancePO.setSourceNodeInstanceId("testSourceNodeInstanceId_" + UUID.randomUUID().toString()); + nodeInstancePO.setNodeInstanceId("testNodeInstanceId_" + UUID.randomUUID()); + nodeInstancePO.setSourceNodeInstanceId("testSourceNodeInstanceId_" + UUID.randomUUID()); return nodeInstancePO; } @@ -461,7 +461,7 @@ public static InstanceDataPO buildInstanceDataPO() { public static InstanceDataPO buildDynamicInstanceDataPO() { InstanceDataPO instanceDataPO = buildInstanceDataPO(); - instanceDataPO.setInstanceDataId("testInstanceDataId_" + System.currentTimeMillis() + new Random().nextInt()); + instanceDataPO.setInstanceDataId("testInstanceDataId_" + UUID.randomUUID()); return instanceDataPO; } diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/util/GroovyUtilTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/util/GroovyUtilTest.java index 17dcfa64..06f7cd06 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/util/GroovyUtilTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/util/GroovyUtilTest.java @@ -2,6 +2,7 @@ import com.didiglobal.turbo.engine.runner.BaseTest; import com.google.common.collect.Maps; +import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,9 +28,12 @@ public class GroovyUtilTest { @Test public void fun1(){ try { - String expression = ""; + String expression = "str.length() > 2"; Map dataMap = Maps.newHashMap(); + dataMap.put("str","1234"); Object result = GroovyUtil.execute(expression, dataMap); + Assert.assertNotNull(result); + Assert.assertTrue((Boolean) result); LOGGER.warn("result:{}:{}", result.getClass().getSimpleName(), result); } catch (Exception e) { LOGGER.warn("catch exception", e); diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/util/IdGeneratorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/util/IdGeneratorTest.java deleted file mode 100644 index b1ebf1c5..00000000 --- a/engine/src/test/java/com/didiglobal/turbo/engine/util/IdGeneratorTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.didiglobal.turbo.engine.util; - -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class IdGeneratorTest { - - private static final Logger LOGGER = LoggerFactory.getLogger(IdGeneratorTest.class); - - private IdGenerator idGenerator = new StrongUuidGenerator(); - - @Test - public void testDoExecute() { - long start = System.currentTimeMillis(); - for (int i = 0; i < 1000000; i++) { - LOGGER.info("{}", idGenerator.getNextId()); - } - - LOGGER.info("{}", System.currentTimeMillis() - start); - } -} diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/validator/EndEventValidatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/validator/EndEventValidatorTest.java index 8d31f73d..78bccf12 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/validator/EndEventValidatorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/validator/EndEventValidatorTest.java @@ -1,5 +1,6 @@ package com.didiglobal.turbo.engine.validator; +import com.didiglobal.turbo.engine.common.ErrorEnum; import com.didiglobal.turbo.engine.exception.DefinitionException; import com.didiglobal.turbo.engine.model.FlowElement; import com.didiglobal.turbo.engine.runner.BaseTest; @@ -8,6 +9,7 @@ import org.junit.Test; import javax.annotation.Resource; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -16,14 +18,14 @@ public class EndEventValidatorTest extends BaseTest { - @Resource EndEventValidator endEventValidator; + @Resource + EndEventValidator endEventValidator; /** * Test endEvent's checkIncoming, while incoming is normal. - * */ @Test - public void checkIncomingAcess() { + public void checkIncomingAccess() { FlowElement endEvent = EntityBuilder.buildEndEvent(); Map map = new HashMap<>(); map.put(endEvent.getKey(), endEvent); @@ -31,17 +33,16 @@ public void checkIncomingAcess() { try { endEventValidator.checkIncoming(map, endEvent); access = true; - Assert.assertTrue(access); } catch (DefinitionException e) { LOGGER.error("", e); - Assert.assertTrue(access); } + Assert.assertTrue(access); + } /** * Test endEvent's checkIncoming, while incoming is null. - * */ @Test public void checkWithoutIncoming() { @@ -53,16 +54,14 @@ public void checkWithoutIncoming() { try { endEventValidator.checkIncoming(map, endEventInvalid); access = true; - Assert.assertFalse(access); } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + Assert.assertEquals(ErrorEnum.ELEMENT_LACK_INCOMING.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } /** * Test endEvent's checkOutgoing, while outgoing is normal. - * */ @Test public void checkOutgoingAccess() { @@ -74,7 +73,6 @@ public void checkOutgoingAccess() { /** * Test endEvent's checkOutgoing, while outgoing is not null. - * */ @Test public void checkOutgoingIsNotNull() { diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/validator/ExclusiveGatewayValidatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/validator/ExclusiveGatewayValidatorTest.java index 6c2acd3a..9b370040 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/validator/ExclusiveGatewayValidatorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/validator/ExclusiveGatewayValidatorTest.java @@ -1,5 +1,6 @@ package com.didiglobal.turbo.engine.validator; +import com.didiglobal.turbo.engine.common.ErrorEnum; import com.didiglobal.turbo.engine.exception.DefinitionException; import com.didiglobal.turbo.engine.model.FlowElement; import com.didiglobal.turbo.engine.runner.BaseTest; @@ -8,6 +9,7 @@ import org.junit.Test; import javax.annotation.Resource; + import java.util.HashMap; import java.util.Map; @@ -20,134 +22,128 @@ public class ExclusiveGatewayValidatorTest extends BaseTest { /** * Test exclusiveGateway's checkIncoming, while exclusiveGateway's incoming is normal. - * */ @Test public void checkIncomingAccess() { - FlowElement exclusiveGateway= EntityBuilder.buildExclusiveGateway(); - FlowElement outgoningSequence = EntityBuilder.buildSequenceFlow2(); - FlowElement outgoningSequence1 = EntityBuilder.buildSequenceFlow3(); + FlowElement exclusiveGateway = EntityBuilder.buildExclusiveGateway(); + FlowElement outGoingSequence = EntityBuilder.buildSequenceFlow2(); + FlowElement outGoingSequence1 = EntityBuilder.buildSequenceFlow3(); Map map = new HashMap<>(); map.put(exclusiveGateway.getKey(), exclusiveGateway); - map.put(outgoningSequence.getKey(), outgoningSequence); - map.put(outgoningSequence1.getKey(), outgoningSequence1); + map.put(outGoingSequence.getKey(), outGoingSequence); + map.put(outGoingSequence1.getKey(), outGoingSequence1); boolean access = false; try { exclusiveGatewayValidator.checkIncoming(map, exclusiveGateway); access = true; - Assert.assertTrue(access); } catch (DefinitionException e) { LOGGER.error("", e); - Assert.assertTrue(access); } + Assert.assertTrue(access); } /** * Test exclusiveGateway's checkIncoming, while incoming is null. - * */ @Test public void checkWithoutIncoming() { - FlowElement exclusiveGateway= EntityBuilder.buildExclusiveGateway(); - FlowElement outgoningSequence = EntityBuilder.buildSequenceFlow2(); - FlowElement outgoningSequence1 = EntityBuilder.buildSequenceFlow3(); + FlowElement exclusiveGateway = EntityBuilder.buildExclusiveGateway(); + FlowElement outGoingSequence = EntityBuilder.buildSequenceFlow2(); + FlowElement outGoingSequence1 = EntityBuilder.buildSequenceFlow3(); exclusiveGateway.setIncoming(null); Map map = new HashMap<>(); map.put(exclusiveGateway.getKey(), exclusiveGateway); - map.put(outgoningSequence.getKey(), outgoningSequence); - map.put(outgoningSequence1.getKey(), outgoningSequence1); + map.put(outGoingSequence.getKey(), outGoingSequence); + map.put(outGoingSequence1.getKey(), outGoingSequence1); boolean access = false; try { exclusiveGatewayValidator.checkIncoming(map, exclusiveGateway); access = true; - Assert.assertFalse(access); } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + Assert.assertEquals(ErrorEnum.ELEMENT_LACK_INCOMING.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } /** * Test exclusiveGateway's checkOutgoing, while exclusiveGateway's outgoing is normal. - * */ @Test public void checkOutgoingAccess() { - FlowElement exclusiveGateway= EntityBuilder.buildExclusiveGateway(); - FlowElement outgoningSequence = EntityBuilder.buildSequenceFlow2(); - FlowElement outgoningSequence1 = EntityBuilder.buildSequenceFlow3(); + FlowElement exclusiveGateway = EntityBuilder.buildExclusiveGateway(); + FlowElement outGoingSequence = EntityBuilder.buildSequenceFlow2(); + FlowElement outGoingSequence1 = EntityBuilder.buildSequenceFlow3(); Map map = new HashMap<>(); map.put(exclusiveGateway.getKey(), exclusiveGateway); - map.put(outgoningSequence.getKey(), outgoningSequence); - map.put(outgoningSequence1.getKey(), outgoningSequence1); + map.put(outGoingSequence.getKey(), outGoingSequence); + map.put(outGoingSequence1.getKey(), outGoingSequence1); boolean access = false; try { exclusiveGatewayValidator.checkOutgoing(map, exclusiveGateway); access = true; - Assert.assertTrue(access); } catch (DefinitionException e) { LOGGER.error("", e); - Assert.assertTrue(access); } + Assert.assertTrue(access); } /** * Test exclusiveGateway's checkOutgoing, while exclusiveGateway's outgoing is empty. - * */ @Test public void checkEmptyOutgoing() { - FlowElement exclusiveGateway= EntityBuilder.buildExclusiveGateway(); - FlowElement outgoningSequence = EntityBuilder.buildSequenceFlow2(); + FlowElement exclusiveGateway = EntityBuilder.buildExclusiveGateway(); + FlowElement outGoingSequence = EntityBuilder.buildSequenceFlow2(); Map properties = new HashMap<>(); properties.put("defaultConditions", "false"); properties.put("conditionsequenceflow", ""); - outgoningSequence.setProperties(properties); + outGoingSequence.setProperties(properties); FlowElement outgoningSequence1 = EntityBuilder.buildSequenceFlow3(); Map map = new HashMap<>(); map.put(exclusiveGateway.getKey(), exclusiveGateway); - map.put(outgoningSequence.getKey(), outgoningSequence); + map.put(outGoingSequence.getKey(), outGoingSequence); map.put(outgoningSequence1.getKey(), outgoningSequence1); boolean access = false; try { exclusiveGatewayValidator.checkOutgoing(map, exclusiveGateway); access = true; - Assert.assertFalse(access); } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + Assert.assertEquals(ErrorEnum.EMPTY_SEQUENCE_OUTGOING.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } /** * Test exclusiveGateway's checkOutgoing, while too many default sequence. - * */ @Test - public void checkTooManySequenceOutgoig() { - FlowElement exclusiveGateway= EntityBuilder.buildExclusiveGateway(); - FlowElement outgoningSequence = EntityBuilder.buildSequenceFlow2(); + public void checkTooManyDefaultSequenceOutgoing() { + FlowElement exclusiveGateway = EntityBuilder.buildExclusiveGateway(); + + FlowElement outGoingSequence = EntityBuilder.buildSequenceFlow2(); Map properties = new HashMap<>(); properties.put("defaultConditions", "true"); properties.put("conditionsequenceflow", ""); - outgoningSequence.setProperties(properties); - FlowElement outgoningSequence1 = EntityBuilder.buildSequenceFlow3(); + outGoingSequence.setProperties(properties); + + FlowElement outGoingSequence1 = EntityBuilder.buildSequenceFlow3(); Map properties1 = new HashMap<>(); - properties.put("defaultConditions", "true"); - properties.put("conditionsequenceflow", ""); - outgoningSequence1.setProperties(properties); + properties1.put("defaultConditions", "true"); + properties1.put("conditionsequenceflow", ""); + outGoingSequence1.setProperties(properties1); + Map map = new HashMap<>(); map.put(exclusiveGateway.getKey(), exclusiveGateway); - map.put(outgoningSequence.getKey(), outgoningSequence); - map.put(outgoningSequence1.getKey(), outgoningSequence1); + map.put(outGoingSequence.getKey(), outGoingSequence); + map.put(outGoingSequence1.getKey(), outGoingSequence1); + boolean access = false; try { exclusiveGatewayValidator.checkOutgoing(map, exclusiveGateway); access = true; - Assert.assertFalse(access); } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + Assert.assertEquals(ErrorEnum.TOO_MANY_DEFAULT_SEQUENCE.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } } \ No newline at end of file diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/validator/FlowModelValidatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/validator/FlowModelValidatorTest.java index 867c439e..19bf11dc 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/validator/FlowModelValidatorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/validator/FlowModelValidatorTest.java @@ -1,5 +1,6 @@ package com.didiglobal.turbo.engine.validator; +import com.didiglobal.turbo.engine.common.ErrorEnum; import com.didiglobal.turbo.engine.common.FlowElementType; import com.didiglobal.turbo.engine.exception.DefinitionException; import com.didiglobal.turbo.engine.exception.ProcessException; @@ -13,17 +14,17 @@ import org.junit.Test; import javax.annotation.Resource; + import java.util.ArrayList; import java.util.List; public class FlowModelValidatorTest extends BaseTest { @Resource - FlowModelValidator flowModelValidator; + private FlowModelValidator flowModelValidator; /** * Test flowModel's validate, while normal. - * */ @Test public void validateAccess() { @@ -34,22 +35,15 @@ public void validateAccess() { try { flowModelValidator.validate(flowModel); access = true; - Assert.assertTrue(access); - } catch (ProcessException e) { - LOGGER.error("", e); - access = true; - Assert.assertTrue(access); - } catch (DefinitionException e) { + } catch (ProcessException | DefinitionException e) { LOGGER.error("", e); - access = true; - Assert.assertTrue(access); } + Assert.assertTrue(access); } /** * Test flowModel's validate, while element's key is not unique. - * */ @Test public void validateElementKeyNotUnique() { @@ -70,19 +64,14 @@ public void validateElementKeyNotUnique() { try { flowModelValidator.validate(flowModel); access = true; - Assert.assertFalse(access); - } catch (ProcessException e) { - LOGGER.error("", e); - Assert.assertFalse(access); - } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + } catch (ProcessException | DefinitionException e) { + Assert.assertEquals(ErrorEnum.ELEMENT_KEY_NOT_UNIQUE.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } /** * Test flowModel's validate, while startEvent's num is not equal 1. - * */ @Test public void validateStartEventNotOne() { @@ -101,39 +90,30 @@ public void validateStartEventNotOne() { try { flowModelValidator.validate(flowModel); access = true; - Assert.assertFalse(access); - } catch (ProcessException e) { - LOGGER.error("", e); - Assert.assertFalse(access); - } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + } catch (ProcessException | DefinitionException e) { + Assert.assertEquals(ErrorEnum.START_NODE_INVALID.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } /** * Test flowModel's validate, while endEvent is null. - * */ @Test public void validateWithoutEndEvent() { List flowElementsList = EntityBuilder.buildFlowElementList(); int flowElementsListSize = flowElementsList.size(); - flowElementsList.remove(flowElementsListSize-1); - flowElementsList.remove(flowElementsListSize-2); + flowElementsList.remove(flowElementsListSize - 1); + flowElementsList.remove(flowElementsListSize - 2); FlowModel flowModel = new FlowModel(); flowModel.setFlowElementList(flowElementsList); boolean access = false; try { flowModelValidator.validate(flowModel); access = true; - Assert.assertFalse(access); - } catch (ProcessException e) { - LOGGER.error("", e); - Assert.assertFalse(access); - } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + } catch (ProcessException | DefinitionException e) { + Assert.assertEquals(ErrorEnum.END_NODE_INVALID.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } } \ No newline at end of file diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/validator/ModelValidatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/validator/ModelValidatorTest.java index c781952d..5ff25782 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/validator/ModelValidatorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/validator/ModelValidatorTest.java @@ -1,5 +1,6 @@ package com.didiglobal.turbo.engine.validator; +import com.didiglobal.turbo.engine.common.ErrorEnum; import com.didiglobal.turbo.engine.exception.DefinitionException; import com.didiglobal.turbo.engine.exception.ProcessException; import com.didiglobal.turbo.engine.runner.BaseTest; @@ -11,11 +12,11 @@ public class ModelValidatorTest extends BaseTest { - @Resource ModelValidator modelValidator; + @Resource + private ModelValidator modelValidator; /** * Test modelValidator, while model is normal. - * */ @Test public void validateAccess() { @@ -24,20 +25,14 @@ public void validateAccess() { try { modelValidator.validate(modelStr); access = true; - Assert.assertTrue(access); - } catch (DefinitionException e) { + } catch (DefinitionException | ProcessException e) { LOGGER.error("", e); - Assert.assertTrue(access); - } catch (ProcessException e) { - LOGGER.error("", e); - Assert.assertTrue(access); } - - + Assert.assertTrue(access); } + /** * Test modelValidator, while model is empty. - * */ @Test public void validateEmptyModel() { @@ -46,14 +41,10 @@ public void validateEmptyModel() { try { modelValidator.validate(modelStr); access = true; - Assert.assertFalse(access); - } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); - } catch (ProcessException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + } catch (DefinitionException | ProcessException e) { + Assert.assertEquals(ErrorEnum.MODEL_EMPTY.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } } \ No newline at end of file diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/validator/SequenceFlowValidatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/validator/SequenceFlowValidatorTest.java index 4c25e853..6748cb46 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/validator/SequenceFlowValidatorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/validator/SequenceFlowValidatorTest.java @@ -1,5 +1,6 @@ package com.didiglobal.turbo.engine.validator; +import com.didiglobal.turbo.engine.common.ErrorEnum; import com.didiglobal.turbo.engine.exception.DefinitionException; import com.didiglobal.turbo.engine.model.FlowElement; import com.didiglobal.turbo.engine.runner.BaseTest; @@ -21,7 +22,6 @@ public class SequenceFlowValidatorTest extends BaseTest { /** * Test sequenceFlow's checkIncoming, while incoming is normal. - * */ @Test public void checkIncomingAccess() { @@ -32,17 +32,15 @@ public void checkIncomingAccess() { try { sequenceFlowValidator.checkIncoming(flowElementMap, sequenceFlow); access = true; - Assert.assertTrue(access); } catch (DefinitionException e) { LOGGER.error("", e); - Assert.assertTrue(access); } + Assert.assertTrue(access); } /** * Test sequenceFlow's checkIncoming, while incoming is too much. - * */ @Test public void checkTooMuchIncoming() { @@ -57,16 +55,14 @@ public void checkTooMuchIncoming() { try { sequenceFlowValidator.checkIncoming(flowElementMap, sequenceFlow); access = true; - Assert.assertFalse(access); } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + Assert.assertEquals(ErrorEnum.ELEMENT_TOO_MANY_INCOMING.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } /** * Test sequenceFlow's checkOutgoing, while outgoing is normal. - * */ @Test public void checkOutgoingAccess() { @@ -78,16 +74,14 @@ public void checkOutgoingAccess() { try { sequenceFlowValidator.checkOutgoing(flowElementMap, sequenceFlow); access = true; - Assert.assertTrue(access); } catch (DefinitionException e) { LOGGER.error("", e); - Assert.assertTrue(access); } + Assert.assertTrue(access); } /** * Test sequenceFlow's outgoing, while outgoing is lack. - * */ @Test public void checkWithoutOutgoing() { @@ -100,10 +94,9 @@ public void checkWithoutOutgoing() { try { sequenceFlowValidator.checkOutgoing(flowElementMap, sequenceFlow); access = true; - Assert.assertFalse(access); } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + Assert.assertEquals(ErrorEnum.ELEMENT_LACK_OUTGOING.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } } \ No newline at end of file diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/validator/StartEventValidatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/validator/StartEventValidatorTest.java index d85a6725..9e2137a4 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/validator/StartEventValidatorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/validator/StartEventValidatorTest.java @@ -1,5 +1,6 @@ package com.didiglobal.turbo.engine.validator; +import com.didiglobal.turbo.engine.common.ErrorEnum; import com.didiglobal.turbo.engine.exception.DefinitionException; import com.didiglobal.turbo.engine.model.FlowElement; import com.didiglobal.turbo.engine.runner.BaseTest; @@ -16,11 +17,11 @@ public class StartEventValidatorTest extends BaseTest { - @Resource StartEventValidator startEventValidator; + @Resource + StartEventValidator startEventValidator; /** - * Test startEvent's incoming, whlile normal. - * + * Test startEvent's incoming, while normal. */ @Test public void checkIncomingAccess() { @@ -29,24 +30,24 @@ public void checkIncomingAccess() { map.put(startEvent.getKey(), startEvent); startEventValidator.checkIncoming(map, startEvent); } + /** - * Test startEvent's incoming, whlile incoming is too much. - * + * Test startEvent's incoming, when there are too many incomings. */ @Test public void checkTooManyIncoming() { - FlowElement startEventVaild = EntityBuilder.buildStartEvent(); + FlowElement startEvent = EntityBuilder.buildStartEvent(); List incomings = new ArrayList<>(); incomings.add("sequence"); - startEventVaild.setIncoming(incomings); + startEvent.setIncoming(incomings); Map map = new HashMap<>(); - map.put("startEvent", startEventVaild); - startEventValidator.checkIncoming(map, startEventVaild); + map.put("startEvent", startEvent); + // A warning log will be printed when the startEvent's incoming exists. + startEventValidator.checkIncoming(map, startEvent); } /** - * Test startEvent's incoming, whlile normal. - * + * Test startEvent's incoming, while normal. */ @Test public void checkOutgoingAccess() { @@ -57,32 +58,29 @@ public void checkOutgoingAccess() { try { startEventValidator.checkOutgoing(map, startEvent); access = true; - Assert.assertTrue(access); } catch (DefinitionException e) { LOGGER.error("", e); - Assert.assertTrue(access); } + Assert.assertTrue(access); } + /** - * Test startEvent's incoming, whlile incoming is too much. - * + * Test startEvent's outgoing, when the outgoing don't exist. */ @Test - public void checkTooMuchOutgoing() { - FlowElement startEventVaild = EntityBuilder.buildStartEvent(); + public void checkEmptyOutgoing() { + FlowElement startEvent = EntityBuilder.buildStartEvent(); List outgoings = new ArrayList<>(); - startEventVaild.setOutgoing(outgoings); + startEvent.setOutgoing(outgoings); Map map = new HashMap<>(); - map.put("startEvent", startEventVaild); + map.put("startEvent", startEvent); boolean access = false; try { - startEventValidator.checkOutgoing(map, startEventVaild); + startEventValidator.checkOutgoing(map, startEvent); access = true; - Assert.assertFalse(access); } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + Assert.assertEquals(ErrorEnum.ELEMENT_LACK_OUTGOING.getErrNo(), e.getErrNo()); } - + Assert.assertFalse(access); } } \ No newline at end of file diff --git a/engine/src/test/java/com/didiglobal/turbo/engine/validator/UserTaskValidatorTest.java b/engine/src/test/java/com/didiglobal/turbo/engine/validator/UserTaskValidatorTest.java index 69d25d94..3dd4b8ac 100644 --- a/engine/src/test/java/com/didiglobal/turbo/engine/validator/UserTaskValidatorTest.java +++ b/engine/src/test/java/com/didiglobal/turbo/engine/validator/UserTaskValidatorTest.java @@ -1,5 +1,6 @@ package com.didiglobal.turbo.engine.validator; +import com.didiglobal.turbo.engine.common.ErrorEnum; import com.didiglobal.turbo.engine.exception.DefinitionException; import com.didiglobal.turbo.engine.model.FlowElement; import com.didiglobal.turbo.engine.runner.BaseTest; @@ -17,8 +18,7 @@ public class UserTaskValidatorTest extends BaseTest { UserTaskValidator userTaskValidator; /** - * Check userTask's incoming, whlile normal. - * + * Check userTask's incoming, while normal. */ @Test public void checkIncomingAccess() { @@ -29,15 +29,14 @@ public void checkIncomingAccess() { try { userTaskValidator.checkIncoming(map, userTask); access = true; - Assert.assertTrue(access); } catch (DefinitionException e) { LOGGER.error("", e); - Assert.assertTrue(access); } + Assert.assertTrue(access); } + /** * Check userTask's incoming, while incoming is lack. - * */ @Test public void checkWithoutIncoming() { @@ -49,17 +48,15 @@ public void checkWithoutIncoming() { try { userTaskValidator.checkIncoming(map, userTask); access = true; - Assert.assertFalse(access); } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + Assert.assertEquals(ErrorEnum.ELEMENT_LACK_INCOMING.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } /** - * Check userTask's outgoing, whlile normal. - * + * Check userTask's outgoing, while normal. */ @Test public void checkOutgoingAccess() { @@ -70,19 +67,17 @@ public void checkOutgoingAccess() { try { userTaskValidator.checkOutgoing(map, userTask); access = true; - Assert.assertTrue(access); } catch (DefinitionException e) { LOGGER.error("", e); - Assert.assertTrue(access); } + Assert.assertTrue(access); } /** * Check userTask's outgoing, while outgoing is lack. - * */ @Test - public void checkWithoutOutgoing() { + public void checkEmptyOutgoing() { FlowElement userTask = EntityBuilder.buildUserTask(); userTask.setOutgoing(null); Map map = new HashMap<>(); @@ -91,10 +86,9 @@ public void checkWithoutOutgoing() { try { userTaskValidator.checkOutgoing(map, userTask); access = true; - Assert.assertFalse(access); } catch (DefinitionException e) { - LOGGER.error("", e); - Assert.assertFalse(access); + Assert.assertEquals(ErrorEnum.ELEMENT_LACK_OUTGOING.getErrNo(), e.getErrNo()); } + Assert.assertFalse(access); } } \ No newline at end of file diff --git a/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator b/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator new file mode 100644 index 00000000..ef39e164 --- /dev/null +++ b/engine/src/test/resources/META-INF/services/com.didiglobal.turbo.engine.spi.calculator.ExpressionCalculator @@ -0,0 +1,2 @@ +com.didiglobal.turbo.engine.spi.calculator.PatternExpressionCalculator +com.didiglobal.turbo.engine.spi.calculator.TestExpressionCalculator diff --git a/engine/src/test/resources/application.properties b/engine/src/test/resources/application.properties index 776e7724..429f5cd2 100644 --- a/engine/src/test/resources/application.properties +++ b/engine/src/test/resources/application.properties @@ -1,14 +1,19 @@ +# h2 +spring.datasource.url=jdbc:h2:mem:test +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.username=root +spring.datasource.password= + spring.datasource.dynamic.primary=engine spring.datasource.dynamic.datasource.engine.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.dynamic.datasource.engine.username=username spring.datasource.dynamic.datasource.engine.password=password -spring.datasource.dynamic.datasource.engine.driver-class-name=com.mysql.jdbc.Driver -spring.datasource.dynamic.datasource.engine.url=jdbc:mysql://127.0.0.1:3306/t_engine?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&autoReconnect=true +spring.datasource.dynamic.datasource.engine.driver-class-name=org.h2.Driver +spring.datasource.dynamic.datasource.engine.url=jdbc:h2:mem:t_engine;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE -mybatis.configuration.map-underscore-to-camel-case=true -logging.config=classpath:logback-spring.xml +# DDL SQL +spring.datasource.schema=classpath:script/turbo-mysql-h2-ddl.sql -hook.url=http://127.0.0.1:8031/globalInfo/refresh -hook.timeout=3000 +logging.config=classpath:logback-spring.xml diff --git a/engine/src/test/resources/script/turbo-mysql-h2-ddl.sql b/engine/src/test/resources/script/turbo-mysql-h2-ddl.sql new file mode 100644 index 00000000..ca95bd27 --- /dev/null +++ b/engine/src/test/resources/script/turbo-mysql-h2-ddl.sql @@ -0,0 +1,141 @@ +CREATE SCHEMA IF NOT EXISTS turbo; + +CREATE TABLE IF NOT EXISTS `em_flow_definition` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', + `flow_name` varchar(64) NOT NULL DEFAULT '' COMMENT '流程名称', + `flow_key` varchar(32) NOT NULL DEFAULT '' COMMENT '流程业务标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `flow_model` mediumtext COMMENT '表单定义', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.初始态 2.编辑中 3.已下线)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', + `operator` varchar(32) NOT NULL DEFAULT '' COMMENT '操作人', + `remark` varchar(512) NOT NULL DEFAULT '' COMMENT '备注', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_flow_module_id` (`flow_module_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='流程定义表'; + +CREATE TABLE IF NOT EXISTS `em_flow_deployment` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', + `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', + `flow_name` varchar(64) NOT NULL DEFAULT '' COMMENT '流程名称', + `flow_key` varchar(32) NOT NULL DEFAULT '' COMMENT '流程业务标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `flow_model` mediumtext COMMENT '表单定义', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.已部署 3.已下线)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', + `operator` varchar(32) NOT NULL DEFAULT '' COMMENT '操作人', + `remark` varchar(512) NOT NULL DEFAULT '' COMMENT '备注', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_flow_deploy_id` (`flow_deploy_id`), + KEY `idx_flow_module_id` (`flow_module_id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='流程部署表'; + +DROP TABLE IF EXISTS `ei_flow_instance`; +CREATE TABLE IF NOT EXISTS `ei_flow_instance` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', + `parent_flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '父流程执行实例id', + `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', + `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.执行完成 2.执行中 3.执行终止(强制终止))', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_flow_instance_id` (`flow_instance_id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8 + ROW_FORMAT = COMPACT COMMENT ='流程执行实例表'; + +CREATE TABLE IF NOT EXISTS `ei_node_instance` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '节点执行实例id', + `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', + `source_node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '上一个节点执行实例id', + `instance_data_id` varchar(128) NOT NULL DEFAULT '' COMMENT '实例数据id', + `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', + `node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '节点唯一标识', + `source_node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '上一个流程节点唯一标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.处理成功 2.处理中 3.处理失败 4.处理已撤销)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_node_instance_id` (`node_instance_id`), + KEY `idx_fiid_sniid_nk` (`flow_instance_id`,`source_node_instance_id`,`node_key`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='节点执行实例表'; + +CREATE TABLE IF NOT EXISTS `ei_node_instance_log` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '节点执行实例id', + `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', + `instance_data_id` varchar(128) NOT NULL DEFAULT '' COMMENT '实例数据id', + `node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '节点唯一标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '操作类型(1.系统执行 2.任务提交 3.任务撤销)', + `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.处理成功 2.处理中 3.处理失败 4.处理已撤销)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='节点执行记录表'; + + +-- 在ei_instance_data表中,如果需要存储表情符号, MySQL的建表语句需要切换utf8mb4 +CREATE TABLE IF NOT EXISTS `ei_instance_data` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '节点执行实例id', + `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', + `instance_data_id` varchar(128) NOT NULL DEFAULT '' COMMENT '实例数据id', + `flow_deploy_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型部署id', + `flow_module_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程模型id', + `node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '节点唯一标识', + `tenant_id` varchar(16) NOT NULL DEFAULT '' COMMENT '业务方标识', + `instance_data` longtext COMMENT '数据列表json', + `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '操作类型(1.实例初始化 2.系统执行 3.系统主动获取 4.上游更新 5.任务提交 6.任务撤回)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT '' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT '' COMMENT '调用方', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_instance_data_id` (`instance_data_id`), + KEY `idx_flow_instance_id` (`flow_instance_id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='节点执行记录表'; + +DROP TABLE IF EXISTS `ei_flow_instance_mapping`; +CREATE TABLE `ei_flow_instance_mapping` +( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', + `flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '流程执行实例id', + `node_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '节点执行实例id', + `node_key` varchar(64) NOT NULL DEFAULT '' COMMENT '节点唯一标识', + `sub_flow_instance_id` varchar(128) NOT NULL DEFAULT '' COMMENT '子流程执行实例id', + `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态(1.执行 2.回滚)', + `create_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程创建时间', + `modify_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '流程修改时间', + `archive` tinyint(4) NOT NULL DEFAULT '0' COMMENT '归档状态(0未删除,1删除)', + `tenant` varchar(100) NOT NULL DEFAULT 'didi' COMMENT '租户', + `caller` varchar(100) NOT NULL DEFAULT 'optimus-prime' COMMENT '调用方', + PRIMARY KEY (`id`), + KEY `idx_fii` (`flow_instance_id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8 + ROW_FORMAT = COMPACT COMMENT ='父子流程实例映射表'; \ No newline at end of file diff --git a/pom.xml b/pom.xml index 90bfb993..ef7360e3 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.didiglobal.turbo turbo pom - 1.1.1 + 1.1.2-SNAPSHOT turbo Turbo is a light-weight flow engine framework, support BPMN2.0 https://www.github.com/didi/turbo @@ -72,6 +72,8 @@ 1.2.83 2.3.7 31.0.1-jre + 1.18.26 + 1.4.200 @@ -141,6 +143,18 @@ guava ${guava.version} + + org.projectlombok + lombok + ${lombok.version} + provided + + + com.h2database + h2 + ${h2.version} + test +