├── LICENSE ├── README.md ├── docs ├── NodeChoose.md ├── ParamSource.md └── QuickStart.md ├── pom.xml ├── taskflow-common ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── taskflow │ └── common │ ├── constant │ └── DagConstant.java │ └── util │ ├── ClassUtil.java │ ├── DagUtil.java │ └── gson │ ├── GsonUtil.java │ ├── NullStringToEmptyAdapterFactory.java │ └── StringNullAdapter.java ├── taskflow-config ├── pom.xml └── src │ ├── main │ └── java │ │ └── org │ │ └── taskflow │ │ └── config │ │ └── op │ │ ├── OpConfig.java │ │ ├── ParamExpressUtil.java │ │ ├── ParamParserHelper.java │ │ ├── enums │ │ └── ParserTypeEnum.java │ │ ├── model │ │ └── JsonPathModel.java │ │ ├── param │ │ ├── JsonPathConfig.java │ │ ├── OpParamConfig.java │ │ └── ParsedParam.java │ │ └── parser │ │ ├── GsonParamParser.java │ │ └── IParamParser.java │ └── test │ └── java │ └── org │ └── taskflow │ └── config │ ├── entity │ └── OpConfigEntity.java │ └── parser │ └── ParamParserTest.java ├── taskflow-core ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── taskflow │ └── core │ ├── DagContextHolder.java │ ├── DagEngine.java │ ├── callback │ ├── ICallable.java │ ├── IChoose.java │ ├── ICondition.java │ └── IDagCallback.java │ ├── context │ └── DagContext.java │ ├── enums │ ├── DagState.java │ ├── ResultState.java │ └── WrapperState.java │ ├── event │ └── OperatorEventEnum.java │ ├── exception │ └── TaskFlowException.java │ ├── listener │ └── OperatorListener.java │ ├── operator │ ├── DefaultParamParseOperator.java │ ├── IOperator.java │ ├── IParamParseOperator.java │ ├── OperatorResult.java │ └── RecurseParamParseOperator.java │ ├── task │ ├── MultiParamTaskResult.java │ ├── TaskResult.java │ └── TaskUtil.java │ ├── thread │ └── pool │ │ ├── CustomThreadFactory.java │ │ └── CustomThreadPool.java │ ├── util │ └── ConvertUtil.java │ └── wrapper │ ├── OperatorWrapper.java │ └── OperatorWrapperGroup.java └── taskflow-example ├── pom.xml └── src └── main └── java └── org └── taskflow └── example ├── callback ├── CallbackTest.java ├── Operator1.java └── Operator2.java ├── choose ├── branch │ ├── ChooseBranchTest.java │ ├── Operator1.java │ ├── Operator2.java │ ├── Operator3.java │ ├── Operator4.java │ ├── Operator5.java │ └── Operator6.java └── op │ ├── group_group │ ├── ChooseOpTest.java │ ├── Operator1.java │ ├── Operator2.java │ ├── Operator3.java │ ├── Operator4.java │ ├── Operator5.java │ └── Operator6.java │ ├── group_op │ ├── ChooseOpTest.java │ ├── Operator1.java │ ├── Operator2.java │ ├── Operator3.java │ ├── Operator4.java │ └── Operator5.java │ ├── nest_group │ ├── ChooseOpTest.java │ ├── Operator1.java │ ├── Operator2.java │ ├── Operator3.java │ ├── Operator4.java │ ├── Operator5.java │ ├── Operator6.java │ ├── Operator7.java │ ├── Operator8.java │ └── Operator9.java │ └── op_op │ ├── ChooseOpTest.java │ ├── Operator1.java │ ├── Operator2.java │ ├── Operator3.java │ └── Operator4.java ├── condition ├── ConditionTest.java ├── Operator1.java ├── Operator2.java ├── Operator3.java ├── Operator4.java └── Operator5.java ├── context ├── ContextTest.java ├── Operator1.java └── Operator2.java ├── dependencytype ├── DependencyTypeTest.java ├── Operator1.java ├── Operator2.java ├── Operator3.java └── Operator4.java ├── endpoint ├── EndpointTest.java ├── Operator1.java ├── Operator2.java ├── Operator3.java └── Operator4.java ├── group ├── GroupTest.java ├── Operator1.java ├── Operator10.java ├── Operator2.java ├── Operator3.java ├── Operator4.java ├── Operator5.java ├── Operator6.java ├── Operator7.java ├── Operator8.java ├── Operator9.java └── nest │ ├── GroupTest.java │ ├── Operator1.java │ ├── Operator2.java │ ├── Operator3.java │ ├── Operator4.java │ ├── Operator5.java │ ├── Operator6.java │ ├── Operator7.java │ ├── Operator8.java │ └── Operator9.java ├── listener ├── ListenerTest.java ├── Operator1.java ├── Operator2.java └── Operator3.java ├── param ├── demo │ ├── Operator1.java │ ├── Operator2.java │ ├── Operator3.java │ └── ParamTest.java ├── demo1 │ ├── Operator1.java │ ├── Operator2.java │ ├── Operator3.java │ └── ParamTest.java ├── demo2 │ ├── Operator1.java │ ├── Operator2.java │ ├── Operator3.java │ ├── Operator4.java │ └── ParamTest.java ├── demo3 │ ├── Operator1.java │ ├── Operator2.java │ ├── Operator3.java │ ├── ParamOperator4.java │ └── ParamTest.java ├── demo4 │ ├── Operator1.java │ ├── ParamOperator2.java │ └── ParamTest.java └── entity │ └── OpConfigEntity.java ├── simpledemo ├── DemoTest.java ├── Operator1.java ├── Operator2.java └── Operator3.java ├── task ├── BatchIntegerOperator.java ├── BatchModelOperator.java ├── IntegerOperator.java ├── Model.java ├── ModelOperator.java ├── ModelResult.java └── TaskTest.java └── threadmodel ├── BlockTest.java ├── NonBlockTest.java └── Operator1.java /README.md: -------------------------------------------------------------------------------- 1 | ### taskflow 2 | --- 3 | >**有向无环图(DAG)**: 4 | > 5 | >1)定义:在图论中,如果一个有向图无法从某个顶点出发经过若干条边回到该点,则这个图是一个[有向无环图(DAG图)](https://baike.baidu.com/item/%E6%9C%89%E5%90%91%E6%97%A0%E7%8E%AF%E5%9B%BE/10972513) 6 | > 7 | >2)有向无环图具有完整严密的拓扑性质,使其具有很强的流程表达能力;通过有向无环图,可以解决两个问题:从逻辑上,对各个节点的依赖关系进行了组织;从技术上,有依赖关系的节点需要等待执行,无依赖关系的可以并发执行 8 | > 9 | > ![vf1pxP.png](https://s1.ax1x.com/2022/08/29/vfYJvn.png) 10 | 11 | --- 12 | >有问题需要沟通、或者有特定的场景需求可以给作者发邮件说明,感谢您的意见。 13 | > 14 | >ytyht226@163.com 15 | 16 | #### 一、项目介绍 17 | 1. **框架简介** 18 | 19 | taskflow是一款轻量、简单易用、可灵活扩展的通用任务编排框架,基于有向无环图(DAG)的方式实现,框架提供了组件复用、同步/异步编排、条件判断、分支选择等能力,可以根据不同的业务场景对任意的业务流程进行编排 20 | 21 | 2. **使用DAG模型的优势** 22 | * 任务模块化 23 | 24 | 对于DAG任务模型,任务之间没有很强的相关性,每个任务模块职责单一,根据输入进行相应的处理,然后输出相应的结果,可复用性极强 25 | * 易于调整 26 | 27 | 基于已有的DAG模型,如果想要调整编排流程,往往只需要修改个别任务即可,可以通过修改图结构或者个别任务的具体实现,即可完成调整 28 | * 结构清晰 29 | 30 | 将业务的处理流程与具体实现进行解耦,根据流程的定义就可以快速的了解整个系统的概况以及包含哪些模块 31 | 32 | 3. **开发语言** 33 | 34 | JDK8+ 35 | 36 | 4. **核心能力** 37 | 38 | ![vf33Of.png](https://s1.ax1x.com/2023/04/13/ppxYvG9.png) 39 | 5. **项目目录** 40 | * taskflow-core: taskflow 引擎核心能力 41 | * taskflow-config: 配置OP参数来源 42 | * taskflow-common: 引擎使用的工具包 43 | * taskflow-example: taskflow 接入实例,提供测试用例 44 | 45 | 6. **名词解释** 46 | 47 | ![vf83C9.png](https://s1.ax1x.com/2022/09/06/v774HS.png) 48 | * **Operator**:以下简称OP或组件,OP是DAG图中具体的节点,如上图1、2、3等节点;实现IOperator接口并开发相应的业务逻辑就可以完成一个OP的定义 49 | * **OperatorWrapper**:以下简称wrapper,OP对应的包装类,在wrapper中可以定义节点的名称、节点与节点之间的关系、节点参数的来源等;引入wrapper后可以将OP进行解耦,根据不同的业务场景需要对OP进行组合使用时,通过wrapper描述OP之间的依赖关系,串联成一个编排流程 50 | * **DagEngine**:DAG执行引擎,根据指定的初始节点(如上图的1、2、3),执行相应的编排流程;DAG执行引擎在初始化时可以指定使用不同的线程池,对业务进行隔离;可以设置整个执行过程的超时时间,达到超时时间阈值时,会结束编排流程的执行,没有执行到的节点不再执行同时执行中的节点也会被中断 51 | * **强依赖**:节点之间默认的依赖关系,只有前面的节点执行结束后才可以执行后续的节点。如上图中 1、2节点执行完才可以执行4;3执行完才可以执行5 52 | * **弱依赖**:在示例图中以虚线表示,不同于强依赖的执行逻辑,只要节点依赖的其它节点中有一个执行结束就可以执行当前节点,如上图中,如果3执行完时,4节点还没有执行完,此时依然可以执行5节点 53 | 54 | #### 二、目标与收益 55 | 1. **通用能力封装** 56 | 57 | * 将项目中常用的功能模块封装成OP组件,这些组件都是通用的,可以在不同的项目中直接使用 58 | * 框架层面统一的日志上报、降级限流、ABtest策略等 59 | 2. **降低开发维护难度** 60 | 61 | * 开发人员只需要实现具体的OP,根据业务逻辑,定义好OP之间的依赖关系(执行流程),不需要编写相对复杂的多线程代码 62 | * 基于编排框架的项目代码风格统一、业务处理流程比较清晰,根据编排流程的定义就可以快速了解整个服务的概况以及包含哪些模块 63 | * 代码的可扩展性好,比如要实现具体某个业务需求时,开发相应的OP然后以插件的形式集成到项目中就可以,不会对其它模块产生影响 64 | 3. **平台化能力建设** 65 | 66 | * 可视化,在页面上可以直观的展示业务的具体处理流程,也可以拖拽的方式对现有流程进行扩展 67 | * 配置化,基于封装的通用OP,可以快速以低代码的方式实现新业务流程的接入 68 | 69 | #### 三、常见的编排场景 70 | 71 | ##### 1. 串行请求 72 | ![vf83C9.png](https://s1.ax1x.com/2022/08/31/v4QAeO.png) 73 | 74 | 1、2、3依次串行执行 75 | ##### 2. 并行请求 76 | ![vf83C9.png](https://s1.ax1x.com/2022/08/31/v4lPhj.png) 77 | 78 | 1、2、3并行执行 79 | ##### 3. 串并行相互依赖 80 | ![vf83C9.png](https://s1.ax1x.com/2022/09/07/vHJ1Nn.png) 81 | 82 | 1执行完后,2、3再并行执行 83 | ##### 4. 弱依赖 84 | ![vf83C9.png](https://s1.ax1x.com/2022/08/31/v4QRpR.png) 85 | 86 | 1、2、3中任意一个执行完后,就可以执行4 87 | ##### 5. 准入条件判断 88 | ![vf83C9.png](https://s1.ax1x.com/2022/08/31/v4Qf6x.png) 89 | 90 | 4弱依赖1、2、3节点,每个节点在执行完后都可以执行4的准入条件,判断当前是否已经满足执行节点4的条件,若满足则直接执行 91 | ##### 6. 分支选择 92 | ![vf83C9.png](https://s1.ax1x.com/2022/09/06/v7Hn4H.png) 93 | 94 | 根据节点的执行结果选择要执行的子节点,如上图所示,最终的执行路径可能是:1->3->6->9 95 | ##### 7. 复杂场景 96 | ![vf83C9.png](https://s1.ax1x.com/2022/09/06/v7HFjx.png) 97 | 98 | 流程复杂,没有严格的串行、并行过程 99 | 100 | #### 四、引擎执行逻辑 101 | ##### 1. 引擎执行的主要流程 102 | 103 | ![vf83C9.png](https://s1.ax1x.com/2023/04/13/ppxNCSs.png) 104 | 105 | ##### 2. 引擎执行流程示例 106 | >DAG图中的节点通过入度(indegree)来表示依赖的节点个数,只有当节点的入度为0时,当前节点才可以执行 107 | 108 | ![vf83C9.png](https://s1.ax1x.com/2023/04/13/ppxtYzn.png) 109 | 110 | >DAG图中的弱依赖不计入节点的入度,如下图中的节点4初始入度等于0 111 | 112 | ![vf83C9.png](https://s1.ax1x.com/2022/09/06/v7Hg54.png) 113 | 114 | >实际的执行流程可能存在三种情况 115 | * 1 -> (2、3)-> 4 -> 5 116 | * 1 -> 2 -> 4 -> 5 117 | * 1 -> 3 -> 4 -> 5 118 | 119 | #### 五、快速开始 120 | [快速开始](docs/QuickStart.md) 121 | -------------------------------------------------------------------------------- /docs/NodeChoose.md: -------------------------------------------------------------------------------- 1 | ### 节点选择 2 | #### 背景 3 | 在某些场景下需要根据节点执行结果执行不同的后续节点,在图中的表现是有分叉,执行分叉的节点后再执行共享的流程,在图中的表现是有合并节点,这种执行情况不同于分支选择 4 | 如下图所示是分支选择的例子,节点1、6是分支选择节点,最终执行的路径可能是1->3->6->9,分支选择之后的流程不能出现合并节点 5 | 6 | ![vfdGnA.png](https://s1.ax1x.com/2023/04/13/ppvx41K.png) 7 | 8 | 如下图是节点选择的例子,节点1是节点选择节点,在后续节点(2、3、4)中选择要执行的节点,最终执行路径可能是1->3->5->6,节点5是合并节点,后续的流程是共享的,不管节点1选择的后续节点是哪个,节点5之后的节点都会执行 9 | 10 | ![vfdGnA.png](https://s1.ax1x.com/2023/04/13/ppvvPKg.png) 11 | 12 | #### 节点选择类型 13 | ##### 1、节点&节点 14 | 这种场景比较简单,待选择的都是单一节点,如下图所示 15 | 16 | ![vfdGnA.png](https://s1.ax1x.com/2023/04/13/ppvzC7j.png) 17 | 18 | 代码示例请参考:[代码示例](../taskflow-example/src/main/java/org/taskflow/example/choose/op/op_op) 19 | ##### 2、节点组&节点 20 | 21 | 参与选择的部分过程比较复杂,需要使用节点组圈定好需要参与选择的节点,其它待选择的就是单一的节点,如下图所示 22 | 23 | ![vfdGnA.png](https://s1.ax1x.com/2023/04/13/ppvzuB4.png) 24 | 25 | 代码示例请参考:[代码示例](../taskflow-example/src/main/java/org/taskflow/example/choose/op/group_op) 26 | ##### 3、节点组&节点组 27 | 28 | 要参与选择的过程都比较复杂,需要使用节点组圈定好需要参与选择的节点,如下图所示 29 | 30 | ![vfdGnA.png](https://s1.ax1x.com/2023/04/13/ppvzNuD.png) 31 | 32 | 代码示例请参考:[代码示例](../taskflow-example/src/main/java/org/taskflow/example/choose/op/group_group) -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.taskflow 8 | taskflow 9 | pom 10 | 1.0.0-SNAPSHOT 11 | 12 | taskflow-core 13 | taskflow-example 14 | taskflow-common 15 | taskflow-config 16 | 17 | 18 | -------------------------------------------------------------------------------- /taskflow-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | org.taskflow 7 | 1.0.0-SNAPSHOT 8 | 9 | taskflow-common 10 | 11 | 12 | 1.8 13 | UTF-8 14 | UTF-8 15 | 16 | 17 | 18 | 19 | com.google.code.gson 20 | gson 21 | 2.9.0 22 | 23 | 24 | 25 | com.jayway.jsonpath 26 | json-path 27 | 2.7.0 28 | 29 | 30 | 31 | org.springframework 32 | spring-core 33 | 5.2.1.RELEASE 34 | 35 | 36 | 37 | org.apache.commons 38 | commons-lang3 39 | 3.3.2 40 | 41 | 42 | 43 | 44 | src/main/java 45 | src/test/java 46 | 47 | 48 | src/main/resources 49 | true 50 | 51 | 52 | 53 | 54 | src/test/resources 55 | true 56 | 57 | 58 | package 59 | 60 | 61 | 62 | 63 | org.apache.maven.plugins 64 | maven-compiler-plugin 65 | 2.3.2 66 | 67 | ${jdk.version} 68 | ${jdk.version} 69 | ${project.build.sourceEncoding} 70 | 71 | 72 | 73 | 74 | org.apache.maven.plugins 75 | maven-source-plugin 76 | 3.1.0 77 | 78 | 79 | attach-sources 80 | 81 | jar 82 | 83 | 84 | 85 | 86 | 87 | org.apache.maven.plugins 88 | maven-surefire-plugin 89 | 2.18.1 90 | 91 | true 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /taskflow-common/src/main/java/org/taskflow/common/constant/DagConstant.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.common.constant; 2 | 3 | /** 4 | * Created by ytyht226 on 2022/11/28. 5 | */ 6 | public interface DagConstant { 7 | /** 8 | * 将请求上下文保存到 DagContext,根据该 id 获取 9 | */ 10 | String REQUEST_CONTEXT_ID = "##request_context_id##"; 11 | /** 12 | * 节点组id前缀 13 | */ 14 | String OP_GROUP_PREFIX = "#op_group#_"; 15 | /** 16 | * 节点组中开始节点id前缀 17 | */ 18 | String BEGIN_OP_IN_GROUP_PREFIX = "#begin#"; 19 | /** 20 | * 节点组中结束节点id前缀 21 | */ 22 | String END_OP_IN_GROUP_PREFIX = "#end#"; 23 | } 24 | -------------------------------------------------------------------------------- /taskflow-common/src/main/java/org/taskflow/common/util/ClassUtil.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.common.util; 2 | 3 | import org.springframework.util.ClassUtils; 4 | 5 | /** 6 | * Created by ytyht226 on 2022/11/28. 7 | */ 8 | public class ClassUtil { 9 | 10 | public static boolean isPrimitive(Class type) { 11 | return ClassUtils.isPrimitiveOrWrapper(type) || type == String.class; 12 | } 13 | } -------------------------------------------------------------------------------- /taskflow-common/src/main/java/org/taskflow/common/util/DagUtil.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.common.util; 2 | 3 | 4 | import org.taskflow.common.constant.DagConstant; 5 | 6 | /** 7 | * Created by ytyht226 on 2023/3/1. 8 | */ 9 | public class DagUtil { 10 | /** 11 | * 当前节点是否节点组 12 | */ 13 | public static boolean isGroupId(String id) { 14 | return id != null && id.startsWith(DagConstant.OP_GROUP_PREFIX); 15 | } 16 | /** 17 | * 当前节点是否节点组中的开始节点 18 | */ 19 | public static boolean isGroupBeginOp(String id) { 20 | return id != null && id.startsWith(DagConstant.BEGIN_OP_IN_GROUP_PREFIX); 21 | } 22 | /** 23 | * 当前节点是否节点组中的结束节点 24 | */ 25 | public static boolean isGroupEndOp(String id) { 26 | return id != null && id.startsWith(DagConstant.END_OP_IN_GROUP_PREFIX); 27 | } 28 | } -------------------------------------------------------------------------------- /taskflow-common/src/main/java/org/taskflow/common/util/gson/GsonUtil.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.common.util.gson; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import com.jayway.jsonpath.spi.json.GsonJsonProvider; 6 | 7 | 8 | public class GsonUtil { 9 | 10 | private static Gson gson = new GsonBuilder() 11 | .serializeNulls() 12 | .registerTypeAdapterFactory(new NullStringToEmptyAdapterFactory<>()) //(值为null转换为"") 13 | .create(); 14 | 15 | private static Gson gsonPrettyPrint = new GsonBuilder() 16 | .setPrettyPrinting() 17 | .registerTypeAdapterFactory(new NullStringToEmptyAdapterFactory<>()) //(值为null转换为"") 18 | .create(); 19 | 20 | private static GsonJsonProvider gsonJsonProvider = new GsonJsonProvider(getGson()); 21 | 22 | private GsonUtil() { 23 | } 24 | 25 | public static Gson getGson() { 26 | return gson; 27 | } 28 | 29 | public static GsonJsonProvider getGsonJsonProvider() { 30 | return gsonJsonProvider; 31 | } 32 | 33 | public static String toJson(Object src) { 34 | return gson.toJson(src); 35 | } 36 | 37 | public static T fromJson(String json, Class classOfT) { 38 | return gson.fromJson(json, classOfT); 39 | } 40 | 41 | public static String prettyPrint(Object src) { 42 | return gsonPrettyPrint.toJson(src); 43 | } 44 | 45 | /** 46 | * 将 value 转换成具体类型的对象 47 | */ 48 | public static Object convertValue(Class typeClass, Object value) { 49 | if (typeClass.isInstance(value)) { 50 | return value; 51 | } 52 | return GsonUtil.fromJson(GsonUtil.toJson(value), typeClass); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /taskflow-common/src/main/java/org/taskflow/common/util/gson/NullStringToEmptyAdapterFactory.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.common.util.gson; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.TypeAdapter; 5 | import com.google.gson.TypeAdapterFactory; 6 | import com.google.gson.reflect.TypeToken; 7 | 8 | public class NullStringToEmptyAdapterFactory implements TypeAdapterFactory { 9 | 10 | @SuppressWarnings("unchecked") 11 | public TypeAdapter create(Gson gson, TypeToken type) { 12 | Class rawType = (Class) type.getRawType(); 13 | if (rawType != String.class) { 14 | return null; 15 | } 16 | return (TypeAdapter) new StringNullAdapter(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /taskflow-common/src/main/java/org/taskflow/common/util/gson/StringNullAdapter.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.common.util.gson; 2 | 3 | 4 | import com.google.gson.TypeAdapter; 5 | import com.google.gson.stream.JsonReader; 6 | import com.google.gson.stream.JsonToken; 7 | import com.google.gson.stream.JsonWriter; 8 | 9 | import java.io.IOException; 10 | 11 | public class StringNullAdapter extends TypeAdapter { 12 | 13 | @Override 14 | public String read(JsonReader reader) throws IOException { 15 | if (reader.peek() == JsonToken.NULL) { 16 | reader.nextNull(); 17 | return ""; 18 | } 19 | return reader.nextString(); 20 | } 21 | 22 | @Override 23 | public void write(JsonWriter writer, String value) throws IOException { 24 | if (value == null) { 25 | writer.nullValue(); 26 | return; 27 | } 28 | writer.value(value); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /taskflow-config/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | org.taskflow 7 | 1.0.0-SNAPSHOT 8 | taskflow-config 9 | 10 | 11 | 1.8 12 | UTF-8 13 | UTF-8 14 | 15 | 16 | 17 | 18 | org.taskflow 19 | taskflow-common 20 | 1.0.0-SNAPSHOT 21 | 22 | 23 | junit 24 | junit 25 | 4.12 26 | provided 27 | 28 | 29 | org.projectlombok 30 | lombok 31 | 1.18.22 32 | 33 | 34 | 35 | 36 | src/main/java 37 | src/test/java 38 | 39 | 40 | src/main/resources 41 | true 42 | 43 | 44 | 45 | 46 | src/test/resources 47 | true 48 | 49 | 50 | package 51 | 52 | 53 | 54 | 55 | org.apache.maven.plugins 56 | maven-compiler-plugin 57 | 2.3.2 58 | 59 | ${jdk.version} 60 | ${jdk.version} 61 | ${project.build.sourceEncoding} 62 | 63 | 64 | 65 | 66 | org.apache.maven.plugins 67 | maven-source-plugin 68 | 3.1.0 69 | 70 | 71 | attach-sources 72 | 73 | jar 74 | 75 | 76 | 77 | 78 | 79 | org.apache.maven.plugins 80 | maven-surefire-plugin 81 | 2.18.1 82 | 83 | true 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /taskflow-config/src/main/java/org/taskflow/config/op/OpConfig.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.config.op; 2 | 3 | import lombok.Data; 4 | import org.taskflow.config.op.param.OpParamConfig; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * OP节点配置 10 | * 包括:入参配置,全局配置等 11 | * Created by ytyht226 on 2022/11/23. 12 | */ 13 | @Data 14 | public class OpConfig { 15 | /** 16 | * OP参数配置 17 | */ 18 | private OpParamConfig opParamConfig; 19 | /** 20 | * 其它配置 21 | */ 22 | private Map extMap; 23 | } -------------------------------------------------------------------------------- /taskflow-config/src/main/java/org/taskflow/config/op/ParamExpressUtil.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.config.op; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.taskflow.common.constant.DagConstant; 5 | import org.taskflow.config.op.model.JsonPathModel; 6 | 7 | /** 8 | * 参数表达式解析工具 9 | * Created by ytyht226 on 2022/11/28. 10 | */ 11 | public class ParamExpressUtil { 12 | /** 从请求上下文取值标志 */ 13 | public static final String REQUEST_CONTEXT_MARK = "#"; 14 | 15 | /** 从依赖的OP执行结果取值标志 */ 16 | public static final String DEPENDENT_MARK = "$"; 17 | 18 | /** 属性分隔符 */ 19 | public static final String PROPERTY_SEPARATOR = "."; 20 | 21 | 22 | public static boolean isJsonPathExpression(String path) { 23 | return StringUtils.isNotBlank(path) && (path.startsWith(REQUEST_CONTEXT_MARK) || path.startsWith(DEPENDENT_MARK)); 24 | } 25 | 26 | /** 27 | * 解析表达式中的任务id、JsonPath表达式 28 | * @return Pair key: 任务id, value: jsonpath表达式 29 | * @see JsonPath 30 | */ 31 | public static JsonPathModel parseJsonPath(String path) { 32 | JsonPathModel jsonPathModel = new JsonPathModel(); 33 | String opId; 34 | String realPath; 35 | if (path.startsWith("#")) { 36 | //eg: #.request.param 37 | opId = DagConstant.REQUEST_CONTEXT_ID; 38 | realPath = path.replace("#", "$"); 39 | } else if (path.startsWith("$")) { 40 | //eg: $1.response.param 41 | if (!path.contains(".")) { 42 | opId = path.substring(1); 43 | realPath = "$"; 44 | } else { 45 | int firstDotIndex = path.indexOf("."); 46 | opId = path.substring(1, firstDotIndex); 47 | realPath = "$" + path.substring(1 + opId.length()); 48 | } 49 | } else { 50 | throw new RuntimeException("jsonPathConfig path error"); 51 | } 52 | jsonPathModel.setOpId(opId); 53 | jsonPathModel.setRealPath(realPath); 54 | return jsonPathModel; 55 | } 56 | } -------------------------------------------------------------------------------- /taskflow-config/src/main/java/org/taskflow/config/op/ParamParserHelper.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.config.op; 2 | 3 | 4 | import org.taskflow.config.op.enums.ParserTypeEnum; 5 | import org.taskflow.config.op.parser.IParamParser; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * 参数解析工具类,默认使用基于gson的json-path解析 11 | * Created by ytyht226 on 2022/11/22. 12 | */ 13 | public class ParamParserHelper { 14 | 15 | public static Object parse(String context, String path) { 16 | return parse(ParserTypeEnum.GSON, context, path); 17 | } 18 | 19 | public static List parse(String context, List pathList) { 20 | return parse(ParserTypeEnum.GSON, context, pathList); 21 | } 22 | 23 | public static T parse(String context, String path, Class type) { 24 | return parse(ParserTypeEnum.GSON, context, path, type); 25 | } 26 | 27 | public static Object parse(ParserTypeEnum parserType, String context, String path) { 28 | IParamParser paramParser = ParserTypeEnum.getParserByType(parserType); 29 | return paramParser.parse(context, path); 30 | } 31 | 32 | public static List parse(ParserTypeEnum parserType, String context, List pathList) { 33 | IParamParser paramParser = ParserTypeEnum.getParserByType(parserType); 34 | return paramParser.parse(context, pathList); 35 | } 36 | 37 | public static T parse(ParserTypeEnum parserType, String context, String path, Class type) { 38 | IParamParser paramParser = ParserTypeEnum.getParserByType(parserType); 39 | return paramParser.parse(context, path, type); 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /taskflow-config/src/main/java/org/taskflow/config/op/enums/ParserTypeEnum.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.config.op.enums; 2 | 3 | 4 | import org.taskflow.config.op.parser.GsonParamParser; 5 | import org.taskflow.config.op.parser.IParamParser; 6 | 7 | /** 8 | * 参数解析器类型枚举 9 | * Created by ytyht226 on 2022/11/22. 10 | */ 11 | public enum ParserTypeEnum { 12 | GSON; 13 | 14 | public static IParamParser getParserByType(ParserTypeEnum typeEnum) { 15 | switch (typeEnum) { 16 | case GSON: 17 | default: 18 | return GsonParamParser.getInstance(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /taskflow-config/src/main/java/org/taskflow/config/op/model/JsonPathModel.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.config.op.model; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 解析表达式中的任务id、JsonPath表达式 7 | * Created by ytyht226 on 2024/1/7. 8 | */ 9 | @Data 10 | public class JsonPathModel { 11 | /** 12 | * 任务id 13 | */ 14 | private String opId; 15 | /** 16 | * jsonpath表达式 17 | */ 18 | private String realPath; 19 | } -------------------------------------------------------------------------------- /taskflow-config/src/main/java/org/taskflow/config/op/param/JsonPathConfig.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.config.op.param; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 参数配置 7 | * Created by ytyht226 on 2022/11/22. 8 | */ 9 | @Data 10 | public class JsonPathConfig { 11 | /** 12 | * 支持两种取值方式:#、$ 13 | * #:从外部变量取值 14 | * $:从其它OP返回结果中取值 15 | */ 16 | private String path; 17 | /** 18 | * 参数类型,全限定名 19 | */ 20 | private String type; 21 | /** 22 | * type类型 23 | */ 24 | private transient Class typeClass; 25 | /** 26 | * 默认值 27 | * 1、path 不存在,返回 value 28 | * 2、path、value 都存在,根据 path 解析报错时,返回 value 29 | * 3、path 存在,value 不存在,根据 path 解析报错,抛异常 30 | */ 31 | private Object value; 32 | } -------------------------------------------------------------------------------- /taskflow-config/src/main/java/org/taskflow/config/op/param/OpParamConfig.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.config.op.param; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * OP参数配置 9 | * Created by ytyht226 on 2022/11/22. 10 | */ 11 | @Data 12 | public class OpParamConfig { 13 | /** 14 | * 要执行的目标对象 15 | */ 16 | private String proxyObjName; 17 | /** 18 | * 要执行的目标方法 19 | */ 20 | private String methodName; 21 | /** 22 | * 入参json-path列表,顺序和类型必须与方法定义一致 23 | */ 24 | private List jsonPathList; 25 | } -------------------------------------------------------------------------------- /taskflow-config/src/main/java/org/taskflow/config/op/param/ParsedParam.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.config.op.param; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 解析后的运行时参数信息 7 | * Created by ytyht226 on 2022/11/23. 8 | */ 9 | @Data 10 | public class ParsedParam { 11 | /** 12 | * 参数类型 13 | */ 14 | private Class[] parameterTypes; 15 | /** 16 | * 参数值 17 | */ 18 | private Object[] args; 19 | } -------------------------------------------------------------------------------- /taskflow-config/src/main/java/org/taskflow/config/op/parser/GsonParamParser.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.config.op.parser; 2 | 3 | import com.jayway.jsonpath.Configuration; 4 | import com.jayway.jsonpath.DocumentContext; 5 | import com.jayway.jsonpath.internal.DefaultsImpl; 6 | import com.jayway.jsonpath.internal.ParseContextImpl; 7 | import org.taskflow.common.util.gson.GsonUtil; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * 基于Gson的参数解析器 14 | * Created by ytyht226 on 2022/11/21. 15 | */ 16 | public class GsonParamParser implements IParamParser { 17 | private static Configuration jsonPathConfiguration = Configuration.builder().jsonProvider(GsonUtil.getGsonJsonProvider()).options(DefaultsImpl.INSTANCE.options()).build(); 18 | private static GsonParamParser gsonParamParser = new GsonParamParser(); 19 | 20 | private GsonParamParser(){ 21 | } 22 | 23 | public static GsonParamParser getInstance() { 24 | return gsonParamParser; 25 | } 26 | 27 | @Override 28 | public Object parse(String context, String path) { 29 | DocumentContext jsonContext = documentContext(context); 30 | return jsonContext.read(path); 31 | } 32 | 33 | @Override 34 | public T parse(String context, String path, Class type) { 35 | DocumentContext jsonContext = documentContext(context); 36 | Object value = jsonContext.read(path); 37 | if (value instanceof String) { 38 | return (T) value; 39 | } 40 | return GsonUtil.fromJson(GsonUtil.toJson(value), type); 41 | } 42 | 43 | @Override 44 | public List parse(String context, List pathList) { 45 | DocumentContext jsonContext = documentContext(context); 46 | List valueList = new ArrayList<>(pathList.size()); 47 | for (String path : pathList) { 48 | valueList.add(jsonContext.read(path)); 49 | } 50 | return valueList; 51 | } 52 | 53 | private DocumentContext documentContext(String context) { 54 | ParseContextImpl parseContext = new ParseContextImpl(jsonPathConfiguration); 55 | return parseContext.parse(context); 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /taskflow-config/src/main/java/org/taskflow/config/op/parser/IParamParser.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.config.op.parser; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by ytyht226 on 2022/11/21. 7 | */ 8 | public interface IParamParser { 9 | 10 | Object parse(String context, String path); 11 | 12 | T parse(String context, String path, Class type); 13 | 14 | List parse(String context, List pathList); 15 | } 16 | -------------------------------------------------------------------------------- /taskflow-config/src/test/java/org/taskflow/config/entity/OpConfigEntity.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.config.entity; 2 | 3 | 4 | import org.taskflow.config.op.OpConfig; 5 | import org.taskflow.config.op.param.JsonPathConfig; 6 | import org.taskflow.config.op.param.OpParamConfig; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.concurrent.ConcurrentHashMap; 12 | 13 | /** 14 | * Created by ytyht226 on 2022/11/23. 15 | */ 16 | public class OpConfigEntity { 17 | 18 | public static OpConfig getOpConfig() { 19 | OpConfig opConfig = new OpConfig(); 20 | 21 | opConfig.setOpParamConfig(getOpParamConfig()); 22 | Map extMap = new ConcurrentHashMap<>(); 23 | extMap.put("city", "bj"); 24 | extMap.put("code", 100); 25 | extMap.put("score", 100.05); 26 | 27 | Map infoMap = new ConcurrentHashMap<>(); 28 | infoMap.put("address", "hd"); 29 | infoMap.put("age", 18); 30 | extMap.put("info", infoMap); 31 | 32 | opConfig.setExtMap(extMap); 33 | 34 | return opConfig; 35 | } 36 | 37 | private static OpParamConfig getOpParamConfig() { 38 | OpParamConfig opParamConfig = new OpParamConfig(); 39 | opParamConfig.setProxyObjName("org.taskflow.config.entity.OpConfigEntity"); 40 | opParamConfig.setMethodName("test"); 41 | opParamConfig.setJsonPathList(getJsonPathConfigList()); 42 | return opParamConfig; 43 | } 44 | 45 | private static List getJsonPathConfigList() { 46 | List jsonPathConfigList = new ArrayList<>(); 47 | 48 | JsonPathConfig config1 = new JsonPathConfig(); 49 | config1.setPath("#.request.param"); 50 | config1.setType("java.lang.String"); 51 | config1.setValue("test"); 52 | 53 | JsonPathConfig config2 = new JsonPathConfig(); 54 | config2.setPath("$1.response.param"); 55 | config2.setType("java.lang.Integer"); 56 | 57 | jsonPathConfigList.add(config1); 58 | jsonPathConfigList.add(config2); 59 | 60 | return jsonPathConfigList; 61 | } 62 | } -------------------------------------------------------------------------------- /taskflow-config/src/test/java/org/taskflow/config/parser/ParamParserTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.config.parser; 2 | 3 | import org.junit.Test; 4 | import org.taskflow.common.util.gson.GsonUtil; 5 | import org.taskflow.config.entity.OpConfigEntity; 6 | import org.taskflow.config.op.OpConfig; 7 | import org.taskflow.config.op.ParamParserHelper; 8 | import org.taskflow.config.op.param.JsonPathConfig; 9 | import org.taskflow.config.op.param.OpParamConfig; 10 | 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | /** 15 | * Created by ytyht226 on 2022/11/21. 16 | */ 17 | public class ParamParserTest { 18 | 19 | @Test 20 | public void test() { 21 | OpConfig opConfig = OpConfigEntity.getOpConfig(); 22 | String str = GsonUtil.toJson(opConfig); 23 | System.out.println(str); 24 | 25 | OpParamConfig opParamConfig = ParamParserHelper.parse(str, "$.opParamConfig", OpParamConfig.class); 26 | String proxyObjName = ParamParserHelper.parse(str, "$.opParamConfig.proxyObjName", String.class); 27 | List jsonPathConfigList = ParamParserHelper.parse(str, "$.opParamConfig.jsonPathList", List.class); 28 | Map extMap = ParamParserHelper.parse(str, "$.extMap", Map.class); 29 | Double score = ParamParserHelper.parse(str, "$.extMap.score", Double.class); 30 | String address = ParamParserHelper.parse(str, "$.extMap.info.address", String.class); 31 | 32 | System.out.println("opParamConfig: " + GsonUtil.prettyPrint(opParamConfig)); 33 | System.out.println("proxyObjName: " + proxyObjName); 34 | System.out.println("jsonPathConfigList: " + GsonUtil.toJson(jsonPathConfigList)); 35 | System.out.println("extMap: " + GsonUtil.toJson(extMap)); 36 | System.out.println("score: " + score); 37 | System.out.println("address: " + address); 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /taskflow-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.taskflow 8 | taskflow-core 9 | 1.0.0-SNAPSHOT 10 | 11 | 12 | 1.8 13 | UTF-8 14 | UTF-8 15 | 1.2.17 16 | 1.7.5 17 | 18 | 19 | 20 | 21 | org.taskflow 22 | taskflow-config 23 | 1.0.0-SNAPSHOT 24 | 25 | 26 | org.projectlombok 27 | lombok 28 | 1.18.22 29 | 30 | 31 | 32 | com.alibaba 33 | transmittable-thread-local 34 | 2.12.3 35 | 36 | 37 | 38 | 39 | log4j 40 | log4j 41 | ${log4j.version} 42 | 43 | 44 | org.slf4j 45 | slf4j-api 46 | ${slf4j.version} 47 | 48 | 49 | org.slf4j 50 | slf4j-log4j12 51 | ${slf4j.version} 52 | 53 | 54 | 55 | com.google.guava 56 | guava 57 | 23.0 58 | 59 | 60 | 61 | 62 | src/main/java 63 | 64 | 65 | src/main/resources 66 | true 67 | 68 | 69 | 70 | 71 | src/test/resources 72 | true 73 | 74 | 75 | package 76 | 77 | 78 | 79 | 80 | org.apache.maven.plugins 81 | maven-compiler-plugin 82 | 2.3.2 83 | 84 | ${jdk.version} 85 | ${jdk.version} 86 | ${project.build.sourceEncoding} 87 | 88 | 89 | 90 | 91 | org.apache.maven.plugins 92 | maven-source-plugin 93 | 3.1.0 94 | 95 | 96 | attach-sources 97 | 98 | jar 99 | 100 | 101 | 102 | 103 | 104 | org.apache.maven.plugins 105 | maven-surefire-plugin 106 | 2.18.1 107 | 108 | true 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/DagContextHolder.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core; 2 | 3 | import com.alibaba.ttl.TransmittableThreadLocal; 4 | import org.taskflow.core.context.DagContext; 5 | import org.taskflow.core.operator.OperatorResult; 6 | 7 | /** 8 | * 获取DagContext上下文的工具类 9 | * Created by ytyht226 on 2022/3/23. 10 | */ 11 | @SuppressWarnings("rawtypes") 12 | public class DagContextHolder { 13 | private static ThreadLocal holder = new TransmittableThreadLocal<>(); 14 | 15 | protected static void set(DagContext dagContext) { 16 | holder.set(dagContext); 17 | } 18 | 19 | public static DagContext get() { 20 | return holder.get(); 21 | } 22 | 23 | protected static void remove() { 24 | holder.remove(); 25 | } 26 | 27 | 28 | public static void putOperatorResult(String wrapperId, OperatorResult operatorResult) { 29 | holder.get().putOperatorResult(wrapperId, operatorResult); 30 | } 31 | 32 | public static OperatorResult getOperatorResult(String wrapperId) { 33 | return holder.get().getOperatorResult(wrapperId); 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/callback/ICallable.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.callback; 2 | 3 | import org.taskflow.core.wrapper.OperatorWrapper; 4 | 5 | /** 6 | * OP执行前后的回调接口 7 | * Created by ytyht226 on 2022/4/8. 8 | */ 9 | @SuppressWarnings("rawtypes") 10 | @FunctionalInterface 11 | public interface ICallable { 12 | 13 | void call(OperatorWrapper wrapper); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/callback/IChoose.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.callback; 2 | 3 | import org.taskflow.core.wrapper.OperatorWrapper; 4 | 5 | import java.util.Set; 6 | 7 | /** 8 | * 分支选择接口,引擎执行过程中,动态的选择当前节点要执行的后继节点 9 | * Created by ytyht226 on 2022/6/24. 10 | */ 11 | @SuppressWarnings("rawtypes") 12 | @FunctionalInterface 13 | public interface IChoose { 14 | Set choose(OperatorWrapper wrapper); 15 | } 16 | -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/callback/ICondition.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.callback; 2 | 3 | import org.taskflow.core.wrapper.OperatorWrapper; 4 | 5 | /** 6 | * 准入条件判断接口,引擎执行过程中,动态的判断是否满足执行该节点的条件 7 | * Created by ytyht226 on 2022/4/8. 8 | */ 9 | @SuppressWarnings("rawtypes") 10 | @FunctionalInterface 11 | public interface ICondition { 12 | 13 | /** 14 | * 判断是否可以执行当前节点 15 | */ 16 | boolean judge(OperatorWrapper wrapper); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/callback/IDagCallback.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.callback; 2 | 3 | /** 4 | * 引擎执行前后的回调接口 5 | * Created by ytyht226 on 2022/3/24. 6 | */ 7 | @FunctionalInterface 8 | public interface IDagCallback { 9 | void callback(); 10 | } -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/context/DagContext.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.context; 2 | 3 | import org.taskflow.core.operator.OperatorResult; 4 | 5 | import java.util.Map; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | 8 | /** 9 | * DAG执行引擎上下文 10 | * 上下文的生命周期是引擎执行期间,即从开始节点到结束节点之间 11 | * Created by ytyht226 on 2022/3/23. 12 | */ 13 | @SuppressWarnings("rawtypes") 14 | public class DagContext { 15 | /** 16 | * 保存每个Operator返回的结果 17 | */ 18 | private Map operatorResultMap = new ConcurrentHashMap<>(); 19 | 20 | public DagContext() { 21 | 22 | } 23 | 24 | public void putOperatorResult(String wrapperId, OperatorResult operatorResult) { 25 | operatorResultMap.put(wrapperId, operatorResult); 26 | } 27 | 28 | public OperatorResult getOperatorResult(String wrapperId) { 29 | return operatorResultMap.get(wrapperId); 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/enums/DagState.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.enums; 2 | 3 | /** 4 | * DAG运行状态枚举 5 | * Created by ytyht226 on 2022/3/17. 6 | */ 7 | public interface DagState { 8 | /** 9 | * 初始状态 10 | */ 11 | int INIT = 0; 12 | /** 13 | * 执行中 14 | */ 15 | int RUNNING = 1; 16 | /** 17 | * 执行结束 18 | */ 19 | int FINISH = 2; 20 | /** 21 | * 执行异常 22 | */ 23 | int ERROR = 3; 24 | } 25 | -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/enums/ResultState.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.enums; 2 | 3 | /** 4 | * 节点执行结果状态枚举 5 | * Created by ytyht226 on 2022/3/17. 6 | */ 7 | public enum ResultState { 8 | /** 9 | * 成功 10 | */ 11 | SUCCESS, 12 | /** 13 | * 超时 14 | */ 15 | TIMEOUT, 16 | /** 17 | * 异常 18 | */ 19 | EXCEPTION, 20 | /** 21 | * 默认 22 | */ 23 | DEFAULT 24 | } -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/enums/WrapperState.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.enums; 2 | 3 | /** 4 | * 节点运行状态枚举 5 | * Created by ytyht226 on 2022/3/17. 6 | */ 7 | public interface WrapperState { 8 | /** 9 | * 初始状态 10 | */ 11 | int INIT = 0; 12 | /** 13 | * 执行中 14 | */ 15 | int RUNNING = 1; 16 | /** 17 | * 执行结束 18 | */ 19 | int FINISH = 2; 20 | /** 21 | * 节点执行异常 22 | */ 23 | int ERROR = 3; 24 | /** 25 | * 跳过当前节点 26 | */ 27 | int SKIP = 4; 28 | } 29 | -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/event/OperatorEventEnum.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.event; 2 | 3 | /** 4 | * 节点执行过程的事件枚举 5 | * Created by ytyht226 on 2022/6/21. 6 | */ 7 | public enum OperatorEventEnum { 8 | START, 9 | SUCCESS, 10 | ERROR 11 | } 12 | -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/exception/TaskFlowException.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.exception; 2 | 3 | /** 4 | * 自定义运行时异常 5 | * Created by ytyht226 on 2022/3/16. 6 | */ 7 | public class TaskFlowException extends RuntimeException { 8 | 9 | public TaskFlowException(String message) { 10 | super(message); 11 | } 12 | 13 | public TaskFlowException(Exception e) { 14 | super(e); 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/listener/OperatorListener.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.listener; 2 | 3 | import org.taskflow.core.event.OperatorEventEnum; 4 | import org.taskflow.core.wrapper.OperatorWrapper; 5 | 6 | /** 7 | * OP执行过程的监听器 8 | * Created by ytyht226 on 2022/6/21. 9 | */ 10 | @SuppressWarnings("rawtypes") 11 | @FunctionalInterface 12 | public interface OperatorListener { 13 | 14 | void onEvent(OperatorWrapper wrapper, OperatorEventEnum eventEnum); 15 | } -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/operator/DefaultParamParseOperator.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.operator; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.taskflow.common.util.gson.GsonUtil; 6 | import org.taskflow.config.op.OpConfig; 7 | import org.taskflow.config.op.ParamExpressUtil; 8 | import org.taskflow.config.op.ParamParserHelper; 9 | import org.taskflow.config.op.model.JsonPathModel; 10 | import org.taskflow.config.op.param.JsonPathConfig; 11 | import org.taskflow.config.op.param.OpParamConfig; 12 | import org.taskflow.config.op.param.ParsedParam; 13 | import org.taskflow.core.DagContextHolder; 14 | import org.taskflow.core.exception.TaskFlowException; 15 | import org.taskflow.core.wrapper.OperatorWrapper; 16 | 17 | import java.lang.reflect.Method; 18 | import java.util.List; 19 | 20 | /** 21 | * 默认的OP入参解析器 22 | * 将参数作为一个整体进行解析,不解析子字段,使用 Gson 序列化/反序列化 23 | * Created by ytyht226 on 2022/11/22. 24 | */ 25 | @Slf4j 26 | @SuppressWarnings("all") 27 | public class DefaultParamParseOperator implements IParamParseOperator { 28 | 29 | @Override 30 | public Object execute(OperatorWrapper param) throws Exception { 31 | Object result = null; 32 | try { 33 | OpConfig opConfig = GsonUtil.fromJson(param.getOpConfig(), OpConfig.class); 34 | 35 | Object proxyObj = param.getProxyObj(); 36 | String proxyObjName = opConfig.getOpParamConfig().getProxyObjName(); 37 | if (proxyObj == null && StringUtils.isBlank(proxyObjName)) { 38 | throw new TaskFlowException("jsonPathConfig error"); 39 | } 40 | if (proxyObj == null) { 41 | //待实现:proxyObj为空时,根据 proxyObjName 从spring容器中获取目标对象,等后续完善好dsl后再实现 42 | throw new TaskFlowException("proxyObj is null"); 43 | } 44 | OpParamConfig opParamConfig = opConfig.getOpParamConfig(); 45 | opParamConfig.setProxyObjName(proxyObjName); 46 | List jsonPathList = opParamConfig.getJsonPathList(); 47 | ParsedParam parsedParam = parseJsonPath(jsonPathList); 48 | 49 | Method targetMethod = proxyObj.getClass().getDeclaredMethod(opParamConfig.getMethodName(), parsedParam.getParameterTypes()); 50 | result = targetMethod.invoke(proxyObj, parsedParam.getArgs()); 51 | } catch (Exception e) { 52 | log.error("ParamParserOperator execute error", e); 53 | throw e; 54 | } 55 | return result; 56 | } 57 | 58 | private ParsedParam parseJsonPath(List jsonPathList) throws Exception { 59 | ParsedParam parsedParam = new ParsedParam(); 60 | Class[] parameterTypes = new Class[jsonPathList.size()]; 61 | Object[] args = new Object[jsonPathList.size()]; 62 | parsedParam.setParameterTypes(parameterTypes); 63 | parsedParam.setArgs(args); 64 | 65 | for (int i = 0; i < jsonPathList.size(); i++) { 66 | JsonPathConfig jsonPathConfig = jsonPathList.get(i); 67 | 68 | Class typeClass = Class.forName(jsonPathConfig.getType()); 69 | jsonPathConfig.setTypeClass(typeClass); 70 | parameterTypes[i] = typeClass; 71 | args[i] = parseArg(jsonPathConfig); 72 | } 73 | return parsedParam; 74 | } 75 | 76 | /** 77 | * 解析逻辑 78 | * 1、path 不存在,直接返回 defaultValue 79 | * 2、path、defaultValue 都存在,根据 path 解析报错,直接返回 defaultValue 80 | * 3、path 存在,defaultValue 不存在,根据 path 解析报错,抛异常 81 | * @param jsonPathConfig 82 | * @return 83 | */ 84 | public Object parseArg(JsonPathConfig jsonPathConfig) { 85 | String path = jsonPathConfig.getPath(); 86 | Object defaultValue = jsonPathConfig.getValue(); 87 | Class typeClass = jsonPathConfig.getTypeClass(); 88 | //path value都为空,配置有误,抛异常 89 | if (StringUtils.isBlank(path) && defaultValue == null) { 90 | throw new TaskFlowException("jsonPathConfig error"); 91 | } 92 | //path为空直接返回value 93 | if (StringUtils.isBlank(path)) { 94 | return convertValue(typeClass, defaultValue); 95 | } 96 | //从请求上下文或其它OP结果中根据jsonpath解析 97 | //解析jsonpath异常时,如果 value 不为空则直接返回,否则抛异常 98 | Object value; 99 | try { 100 | JsonPathModel jsonPathModel = ParamExpressUtil.parseJsonPath(path); 101 | String opId = jsonPathModel.getOpId(); 102 | String realPath = jsonPathModel.getRealPath(); 103 | OperatorResult operatorResult = DagContextHolder.getOperatorResult(opId); 104 | Object result = operatorResult.getResult(); 105 | value = ParamParserHelper.parse(GsonUtil.toJson(result), realPath, typeClass); 106 | } catch (Exception e) { 107 | log.error("parseArg error", e); 108 | if (defaultValue != null) { 109 | return convertValue(typeClass, defaultValue); 110 | } else { 111 | throw new TaskFlowException(e); 112 | } 113 | } 114 | return value; 115 | } 116 | 117 | /** 118 | * 将 value 转换成具体类型的对象 119 | */ 120 | public Object convertValue(Class typeClass, Object value) { 121 | return GsonUtil.convertValue(typeClass, value); 122 | } 123 | } -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/operator/IOperator.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.operator; 2 | 3 | /** 4 | * Operator接口 5 | * Created by ytyht226 on 2022/3/16. 6 | */ 7 | @FunctionalInterface 8 | public interface IOperator { 9 | 10 | /** 11 | * 自定义OP的默认返回值,比如节点执行异常时 12 | */ 13 | default V defaultValue() { 14 | return null; 15 | } 16 | 17 | /** 18 | * 该方法实现OP的具体处理逻辑 19 | */ 20 | V execute(P param) throws Exception; 21 | 22 | /** 23 | * OP执行前回调 24 | */ 25 | default void onStart(P param) { 26 | } 27 | /** 28 | * OP执行成功后回调 29 | */ 30 | default void onSuccess(P param, OperatorResult result) { 31 | } 32 | /** 33 | * OP执行异常后回调 34 | */ 35 | default void onError(P param, OperatorResult result) { 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/operator/IParamParseOperator.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.operator; 2 | 3 | /** 4 | * OP参数解析接口 5 | * Created by ytyht226 on 2022/11/28. 6 | */ 7 | public interface IParamParseOperator extends IOperator{ 8 | } -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/operator/OperatorResult.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.operator; 2 | 3 | import org.taskflow.core.enums.ResultState; 4 | 5 | /** 6 | * Operator执行结果 7 | * Created by ytyht226 on 2022/3/17. 8 | */ 9 | public class OperatorResult { 10 | /** 11 | * 执行的结果 12 | */ 13 | private V result; 14 | /** 15 | * 结果状态 16 | */ 17 | private ResultState resultState; 18 | /** 19 | * 异常信息 20 | */ 21 | private Throwable ex; 22 | 23 | public OperatorResult(V result, ResultState resultState) { 24 | this(result, resultState, null); 25 | } 26 | 27 | public OperatorResult(V result, ResultState resultState, Exception ex) { 28 | this.result = result; 29 | this.resultState = resultState; 30 | this.ex = ex; 31 | } 32 | 33 | public static OperatorResult defaultResult() { 34 | return new OperatorResult<>(null, ResultState.DEFAULT); 35 | } 36 | 37 | @Override 38 | public String toString() { 39 | return "OperatorResult{" + 40 | "result=" + result + 41 | ", resultState=" + resultState + 42 | ", ex=" + ex + 43 | '}'; 44 | } 45 | 46 | public Throwable getEx() { 47 | return ex; 48 | } 49 | 50 | public void setEx(Throwable ex) { 51 | this.ex = ex; 52 | } 53 | 54 | public V getResult() { 55 | return result; 56 | } 57 | 58 | public void setResult(V result) { 59 | this.result = result; 60 | } 61 | 62 | public ResultState getResultState() { 63 | return resultState; 64 | } 65 | 66 | public void setResultState(ResultState resultState) { 67 | this.resultState = resultState; 68 | } 69 | } -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/operator/RecurseParamParseOperator.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.operator; 2 | 3 | import com.google.gson.JsonArray; 4 | import com.google.gson.JsonElement; 5 | import com.google.gson.JsonObject; 6 | import org.taskflow.common.util.ClassUtil; 7 | import org.taskflow.common.util.gson.GsonUtil; 8 | import org.taskflow.config.op.ParamExpressUtil; 9 | import org.taskflow.config.op.ParamParserHelper; 10 | import org.taskflow.config.op.model.JsonPathModel; 11 | import org.taskflow.core.DagContextHolder; 12 | 13 | import java.util.Map; 14 | 15 | /** 16 | * OP入参解析器 17 | * 递归地解析参数的子字段 18 | * Created by ytyht226 on 2022/11/28. 19 | */ 20 | public class RecurseParamParseOperator extends DefaultParamParseOperator { 21 | 22 | @Override 23 | public Object convertValue(Class typeClass, Object value) { 24 | if (ClassUtil.isPrimitive(typeClass)) { 25 | return super.convertValue(typeClass, value); 26 | } 27 | JsonElement rootElement = GsonUtil.getGson().toJsonTree(value); 28 | 29 | Object processedValue = processValue(rootElement); 30 | return super.convertValue(typeClass, processedValue); 31 | } 32 | 33 | /** 34 | * 递归解析节点内容 35 | */ 36 | private Object processValue(JsonElement element) { 37 | 38 | if (element.isJsonObject()) { 39 | JsonObject objElement = (JsonObject) element; 40 | for (Map.Entry entry : ((JsonObject) element).entrySet()) { 41 | Object value = processValue(entry.getValue()); 42 | objElement.add(entry.getKey(), (JsonElement) value); 43 | } 44 | } else if (element.isJsonArray()) { 45 | JsonArray arrElement = (JsonArray) element; 46 | for (int i = 0; i < arrElement.size(); i++) { 47 | Object value = processValue(arrElement.get(i)); 48 | arrElement.set(i, (JsonElement)value); 49 | } 50 | } else { 51 | String path = element.getAsString(); 52 | if (!ParamExpressUtil.isJsonPathExpression(path)) { 53 | return element; 54 | } 55 | Object parsedValue = parsePathValue(path); 56 | return parsedValue; 57 | } 58 | return element; 59 | } 60 | 61 | /** 62 | * 根据path从引擎上下文中解析具体内容 63 | */ 64 | private Object parsePathValue(String path) { 65 | JsonPathModel jsonPathModel = ParamExpressUtil.parseJsonPath(path); 66 | String opId = jsonPathModel.getOpId(); 67 | String realPath = jsonPathModel.getRealPath(); 68 | OperatorResult operatorResult = DagContextHolder.getOperatorResult(opId); 69 | Object result = operatorResult.getResult(); 70 | return ParamParserHelper.parse(GsonUtil.toJson(result), realPath); 71 | } 72 | } -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/task/MultiParamTaskResult.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.task; 2 | 3 | import lombok.Data; 4 | import org.taskflow.core.wrapper.OperatorWrapper; 5 | 6 | import java.util.List; 7 | 8 | 9 | /** 10 | * 任务入参及结果 11 | * 参数可以传入多个,比如批量查询接口 12 | * @param

执行任务的入参类型 13 | * @param 任务执行结果类型 14 | * Created by ytyht226 on 2023/3/17. 15 | */ 16 | @Data 17 | public class MultiParamTaskResult { 18 | /** 19 | * 任务入参 20 | */ 21 | private P obj; 22 | /** 23 | * 任务结果 24 | */ 25 | private V data; 26 | /** 27 | * 任务执行状态,data为空时,可以查看执行的信息 28 | */ 29 | private transient OperatorWrapper, List>> operatorWrapper; 30 | 31 | public MultiParamTaskResult(P obj) { 32 | this.obj = obj; 33 | } 34 | 35 | public MultiParamTaskResult(P obj, V data) { 36 | this.obj = obj; 37 | this.data = data; 38 | } 39 | 40 | public MultiParamTaskResult(P obj, OperatorWrapper, List>> operatorWrapper) { 41 | this.obj = obj; 42 | this.operatorWrapper = operatorWrapper; 43 | } 44 | 45 | public MultiParamTaskResult(P obj, V data, OperatorWrapper, List>> operatorWrapper) { 46 | this.obj = obj; 47 | this.data = data; 48 | this.operatorWrapper = operatorWrapper; 49 | } 50 | } -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/task/TaskResult.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.task; 2 | 3 | import lombok.Data; 4 | import org.taskflow.core.wrapper.OperatorWrapper; 5 | 6 | 7 | /** 8 | * 任务入参及结果 9 | * @param

执行任务的入参类型 10 | * @param 任务执行结果类型 11 | * Created by ytyht226 on 2023/3/17. 12 | */ 13 | @Data 14 | public class TaskResult { 15 | /** 16 | * 任务入参 17 | */ 18 | private P obj; 19 | /** 20 | * 任务结果 21 | */ 22 | private V data; 23 | /** 24 | * 任务执行状态,data为空时,可以查看执行的信息 25 | */ 26 | private transient OperatorWrapper operatorWrapper; 27 | 28 | public TaskResult(P obj) { 29 | this.obj = obj; 30 | } 31 | 32 | public TaskResult(P obj, V data) { 33 | this.obj = obj; 34 | this.data = data; 35 | } 36 | 37 | public TaskResult(P obj, OperatorWrapper operatorWrapper) { 38 | this.obj = obj; 39 | this.operatorWrapper = operatorWrapper; 40 | } 41 | 42 | public TaskResult(P obj, V data, OperatorWrapper operatorWrapper) { 43 | this.obj = obj; 44 | this.data = data; 45 | this.operatorWrapper = operatorWrapper; 46 | } 47 | } -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/thread/pool/CustomThreadFactory.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.thread.pool; 2 | 3 | 4 | import java.util.concurrent.ThreadFactory; 5 | import java.util.concurrent.atomic.AtomicInteger; 6 | 7 | /** 8 | * 自定义线程工厂 9 | * Created by ytyht226 on 2023/3/3. 10 | */ 11 | public class CustomThreadFactory implements ThreadFactory { 12 | private static final AtomicInteger POOL_SEQ = new AtomicInteger(1); 13 | 14 | private final AtomicInteger mThreadNum = new AtomicInteger(1); 15 | 16 | private final String mPrefix; 17 | 18 | private final boolean mDaemon; 19 | 20 | private ThreadGroup threadGroup; 21 | 22 | public CustomThreadFactory() { 23 | this("taskFlow-" + POOL_SEQ.getAndIncrement(), true); 24 | } 25 | 26 | public CustomThreadFactory(String prefix) { 27 | this(prefix, true); 28 | } 29 | 30 | public CustomThreadFactory(String prefix, boolean daemon) { 31 | mPrefix = prefix + "-thread-"; 32 | mDaemon = daemon; 33 | SecurityManager s = System.getSecurityManager(); 34 | threadGroup = (s == null) ? Thread.currentThread().getThreadGroup() : s.getThreadGroup(); 35 | } 36 | 37 | public static CustomThreadFactory newInstance() { 38 | return new CustomThreadFactory(); 39 | } 40 | 41 | public ThreadGroup getThreadGroup() { 42 | return threadGroup; 43 | } 44 | 45 | public void setThreadGroup(ThreadGroup threadGroup) { 46 | this.threadGroup = threadGroup; 47 | } 48 | 49 | @Override 50 | public Thread newThread(Runnable runnable) { 51 | String name = mPrefix + mThreadNum.getAndIncrement(); 52 | Thread ret = new Thread(threadGroup, runnable, name, 0); 53 | ret.setDaemon(mDaemon); 54 | return ret; 55 | } 56 | } -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/thread/pool/CustomThreadPool.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.thread.pool; 2 | 3 | import com.alibaba.ttl.threadpool.TtlExecutors; 4 | 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.LinkedBlockingQueue; 7 | import java.util.concurrent.ThreadPoolExecutor; 8 | import java.util.concurrent.TimeUnit; 9 | 10 | /** 11 | * 自定义线程池 12 | * Created by ytyht226 on 2023/3/3. 13 | */ 14 | public class CustomThreadPool { 15 | 16 | /** 17 | * 固定线程,推荐使用 18 | */ 19 | public static ExecutorService newFixedThreadPoolWrapper(int nThreads) { 20 | return TtlExecutors.getTtlExecutorService(newFixedThreadPool(nThreads)); 21 | } 22 | 23 | /** 24 | * 固定线程 25 | */ 26 | public static ExecutorService newFixedThreadPool(int nThreads) { 27 | return new ThreadPoolExecutor( 28 | nThreads, 29 | nThreads, 30 | 0L, 31 | TimeUnit.MILLISECONDS, 32 | new LinkedBlockingQueue<>(), 33 | CustomThreadFactory.newInstance()); 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/util/ConvertUtil.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.util; 2 | 3 | 4 | import org.taskflow.core.wrapper.OperatorWrapper; 5 | 6 | import java.util.Set; 7 | 8 | /** 9 | * 类型转换工具 10 | * Created by ytyht226 on 2023/3/2. 11 | */ 12 | public class ConvertUtil { 13 | 14 | @SuppressWarnings("rawtypes") 15 | public static OperatorWrapper[] set2Array(Set> wrapperSet) { 16 | if (wrapperSet == null || wrapperSet.size() == 0) { 17 | return new OperatorWrapper[0]; 18 | } 19 | return wrapperSet.toArray(new OperatorWrapper[0]); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /taskflow-core/src/main/java/org/taskflow/core/wrapper/OperatorWrapperGroup.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.core.wrapper; 2 | 3 | import com.google.common.collect.Sets; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.taskflow.common.constant.DagConstant; 6 | import org.taskflow.core.DagEngine; 7 | import org.taskflow.core.operator.IOperator; 8 | 9 | import java.util.HashMap; 10 | import java.util.HashSet; 11 | import java.util.Set; 12 | 13 | /** 14 | * OP节点组,将多个节点抽象成一个组,可以简化对节点依赖的管理,尤其是DAG中节点比较多时 15 | * 根据依赖关系划分成多个组,每个组内的节点可以单独管理,比如系统中涉及多个模块,每个模块又有多个OP节点 16 | * Created by ytyht226 on 2022/4/6. 17 | */ 18 | @SuppressWarnings("all") 19 | public class OperatorWrapperGroup extends OperatorWrapper{ 20 | /** 21 | * 节点组开始节点OP 22 | */ 23 | private static final GroupBeginOperator groupBeginOperator = new GroupBeginOperator(); 24 | /** 25 | * 节点组结束节点OP 26 | */ 27 | private static final GroupEndOperator groupEndOperator = new GroupEndOperator(); 28 | /** 29 | * DAG执行引擎 30 | */ 31 | private DagEngine engine; 32 | /** 33 | * 分组的开始节点,相当于原始开始节点的代理,只进行参数传递 34 | */ 35 | private OperatorWrapper groupBegin; 36 | /** 37 | * 分组的结束节点,相当于原始结束节点的代理,只进行参数传递 38 | */ 39 | private OperatorWrapper groupEnd; 40 | /** 41 | * 分组的开始节点id 42 | */ 43 | private String groupBeginId; 44 | /** 45 | * 分组的结束节点id 46 | */ 47 | private String groupEndId; 48 | /** 49 | * 原始的开始节点 50 | */ 51 | private String[] beginWrapperIds; 52 | /** 53 | * 原始的结束节点 54 | */ 55 | private String[] endWrapperIds; 56 | /** 57 | * 节点组包含的子节点(组) 58 | */ 59 | private Set childrenIds; 60 | 61 | public OperatorWrapperGroup() { 62 | 63 | } 64 | 65 | public OperatorWrapperGroup(DagEngine engine) { 66 | this.engine = engine; 67 | } 68 | 69 | /** 70 | * 初始化,根据原始开始/结束节点,生成对应的节点组的开始/结束节点,只初始化一次 71 | */ 72 | public OperatorWrapperGroup init() { 73 | if (this.isInit()) { 74 | return this; 75 | } 76 | this.setInit(true); 77 | groupBeginId = beginWrapperIds == null ? buildGroupBeginEndId(true, String.valueOf(this.hashCode())) : groupBeginId; 78 | groupEndId = endWrapperIds == null ? buildGroupBeginEndId(false, String.valueOf(this.hashCode())) : groupEndId; 79 | beginWrapperIds = beginWrapperIds == null ? new String[]{groupEndId} : beginWrapperIds; 80 | endWrapperIds = endWrapperIds == null ? new String[]{groupBeginId} : endWrapperIds; 81 | 82 | //根据原始开始节点,生成对应的节点组的开始节点 83 | OperatorWrapper groupBegin = new OperatorWrapper(groupBeginId, groupBeginOperator); 84 | groupBegin.id(groupBeginId) 85 | .engine(engine) 86 | .group(this) 87 | .next(beginWrapperIds); 88 | engine.getWrapperMap().put(groupBeginId, groupBegin); 89 | this.groupBegin = groupBegin; 90 | 91 | //根据原始结束节点,生成对应的节点组的结束节点 92 | OperatorWrapper groupEnd = new OperatorWrapper(groupEndId, groupEndOperator); 93 | groupEnd.id(groupEndId) 94 | .engine(engine) 95 | .group(this) 96 | .addParamFromWrapperId(endWrapperIds); 97 | engine.getWrapperMap().put(groupEndId, groupEnd); 98 | this.groupEnd = groupEnd; 99 | 100 | //设置节点组开始节点 101 | buildGroupBegin(beginWrapperIds); 102 | //设置节点组结束节点 103 | buildGroupEnd(endWrapperIds); 104 | //将节点组保存到引擎 105 | String groupId = StringUtils.isNotBlank(this.getId()) ? this.getId() : groupBeginId; 106 | groupId = buildGroupId(groupId); 107 | this.setId(groupId); 108 | if (engine.getWrapperGroupMap() == null) { 109 | engine.setWrapperGroupMap(new HashMap<>()); 110 | } 111 | engine.getWrapperGroupMap().put(groupId, this); 112 | return this; 113 | } 114 | 115 | public OperatorWrapper context(Object context) { 116 | groupBegin.context(context); 117 | return this; 118 | } 119 | /** 120 | * 节点组也是一种特殊的节点,可以添加依赖的参数来源 121 | */ 122 | public OperatorWrapper addParamFromWrapperId(String ... fromWrapperIds) { 123 | groupBegin.addParamFromWrapperId(fromWrapperIds); 124 | return this; 125 | } 126 | 127 | /** 128 | * 设置节点组开始节点 129 | */ 130 | private OperatorWrapperGroup buildGroupBegin(String ... nextWrapperIds) { 131 | 132 | for (String wrapperId : nextWrapperIds) { 133 | OperatorWrapper wrapper = engine.getWrapperMap().get(wrapperId); 134 | if (wrapper.getParamFromList() == null && wrapper.getContext() == null) { 135 | try { 136 | wrapper.getOperator().getClass().getDeclaredMethod("execute", Void.class); 137 | } catch (NoSuchMethodException e) { 138 | //execute接口有入参,且节点没有指定参数来源时,设置参数来源是节点组的开始节点 139 | wrapper.addParamFromWrapperId(groupBeginId); 140 | } 141 | } 142 | } 143 | return this; 144 | } 145 | 146 | /** 147 | * 设置节点组结束节点 148 | */ 149 | private OperatorWrapperGroup buildGroupEnd(String ... dependWrapperIds) { 150 | 151 | for (String wrapperId : dependWrapperIds) { 152 | engine.getWrapperMap().get(wrapperId).next(groupEnd.getId()); 153 | } 154 | return this; 155 | } 156 | 157 | /** 158 | * 添加节点组结束节点的后续节点 159 | */ 160 | public OperatorWrapper next(String ... wrapperIds) { 161 | this.init(); 162 | engine.getWrapperMap().get(groupEndId).next(wrapperIds); 163 | return super.next(wrapperIds); 164 | } 165 | 166 | public OperatorWrapperGroup id(String id) { 167 | this.setId(id); 168 | return this; 169 | } 170 | 171 | public OperatorWrapperGroup beginWrapperIds(String ... wrapperIds) { 172 | this.beginWrapperIds = wrapperIds; 173 | this.groupBeginId = buildGroupBeginEndId(true, beginWrapperIds); 174 | return this; 175 | } 176 | 177 | public OperatorWrapperGroup endWrapperIds(String ... wrapperIds) { 178 | this.endWrapperIds = wrapperIds; 179 | this.groupEndId = buildGroupBeginEndId(false, endWrapperIds); 180 | return this; 181 | } 182 | 183 | public OperatorWrapperGroup children(String ... wrapperIds) { 184 | if (wrapperIds == null) { 185 | return this; 186 | } 187 | if (childrenIds == null) { 188 | childrenIds = new HashSet<>(); 189 | } 190 | childrenIds.addAll(Sets.newHashSet(wrapperIds)); 191 | return this; 192 | } 193 | 194 | /** 195 | * 构造开始/结束节点的id 196 | */ 197 | private String buildGroupBeginEndId(boolean isBegin, String ... ids) { 198 | if (ids == null) { 199 | return null; 200 | } 201 | String prefix = isBegin ? DagConstant.BEGIN_OP_IN_GROUP_PREFIX : DagConstant.END_OP_IN_GROUP_PREFIX; 202 | StringBuilder builder = new StringBuilder(prefix); 203 | for (String id : ids) { 204 | builder.append("_").append(id); 205 | } 206 | return builder.toString(); 207 | } 208 | 209 | /** 210 | * 根据节点组开始节点id构造节点组id 211 | */ 212 | private String buildGroupId(String groupBeginId) { 213 | return DagConstant.OP_GROUP_PREFIX + groupBeginId; 214 | } 215 | 216 | /** 217 | * 节点组的开始节点OP 218 | */ 219 | public static class GroupBeginOperator implements IOperator { 220 | 221 | @Override 222 | public Object execute(Object param) throws Exception { 223 | return param; 224 | } 225 | } 226 | 227 | /** 228 | * 节点组的结束节点OP 229 | */ 230 | public static class GroupEndOperator implements IOperator { 231 | 232 | @Override 233 | public Object execute(Object param) throws Exception { 234 | return param; 235 | } 236 | } 237 | 238 | public String getGroupBeginId() { 239 | return groupBeginId; 240 | } 241 | 242 | public String getGroupEndId() { 243 | return groupEndId; 244 | } 245 | 246 | public String[] getBeginWrapperIds() { 247 | return beginWrapperIds; 248 | } 249 | 250 | public void setBeginWrapperIds(String[] beginWrapperIds) { 251 | this.beginWrapperIds = beginWrapperIds; 252 | } 253 | 254 | public String[] getEndWrapperIds() { 255 | return endWrapperIds; 256 | } 257 | 258 | public void setEndWrapperIds(String[] endWrapperIds) { 259 | this.endWrapperIds = endWrapperIds; 260 | } 261 | 262 | public OperatorWrapper getGroupBegin() { 263 | return groupBegin; 264 | } 265 | 266 | public Set getChildrenIds() { 267 | return childrenIds; 268 | } 269 | 270 | public OperatorWrapper getGroupEnd() { 271 | return groupEnd; 272 | } 273 | } -------------------------------------------------------------------------------- /taskflow-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.taskflow 8 | taskflow-example 9 | 1.0.0-SNAPSHOT 10 | 11 | 12 | 1.8 13 | UTF-8 14 | UTF-8 15 | 16 | 17 | 18 | 19 | org.taskflow 20 | taskflow-core 21 | 1.0.0-SNAPSHOT 22 | 23 | 24 | 25 | com.google.guava 26 | guava 27 | 23.0 28 | 29 | 30 | 31 | junit 32 | junit 33 | 4.12 34 | provided 35 | 36 | 37 | 38 | 39 | src/main/java 40 | src/test/java 41 | 42 | 43 | src/main/resources 44 | true 45 | 46 | 47 | 48 | 49 | src/test/resources 50 | true 51 | 52 | 53 | package 54 | 55 | 56 | 57 | 58 | org.apache.maven.plugins 59 | maven-compiler-plugin 60 | 2.3.2 61 | 62 | ${jdk.version} 63 | ${jdk.version} 64 | ${project.build.sourceEncoding} 65 | 66 | 67 | 68 | 69 | org.apache.maven.plugins 70 | maven-source-plugin 71 | 3.1.0 72 | 73 | 74 | attach-sources 75 | 76 | jar 77 | 78 | 79 | 80 | 81 | 82 | org.apache.maven.plugins 83 | maven-surefire-plugin 84 | 2.18.1 85 | 86 | true 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/callback/CallbackTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.callback; 2 | 3 | import org.taskflow.core.DagEngine; 4 | import org.taskflow.core.thread.pool.CustomThreadPool; 5 | import org.taskflow.core.wrapper.OperatorWrapper; 6 | import org.junit.Test; 7 | 8 | import java.util.concurrent.ExecutorService; 9 | 10 | /** 11 | * 回调接口:引擎回调、OP回调 12 | * Created by ytyht226 on 2022/6/23. 13 | */ 14 | public class CallbackTest { 15 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 16 | Operator1 operator1 = new Operator1(); 17 | Operator2 operator2 = new Operator2(); 18 | 19 | @Test 20 | public void test() { 21 | DagEngine engine = new DagEngine(executor); 22 | //引擎回调 23 | engine.before(() -> { 24 | System.out.println("engine start..."); 25 | }); 26 | engine.after(() -> { 27 | System.out.println("engine end..."); 28 | }); 29 | //每个OP的回调 30 | engine.beforeOp((w) -> { 31 | System.out.println("OP: " + w.getId() + " start..."); 32 | }); 33 | engine.afterOp((w) -> { 34 | System.out.println("OP: " + w.getId() + " end..."); 35 | }); 36 | OperatorWrapper wrapper1 = new OperatorWrapper() 37 | .id("1") 38 | .engine(engine) 39 | .operator(operator1) 40 | .next("2") 41 | ; 42 | 43 | OperatorWrapper wrapper2 = new OperatorWrapper() 44 | .id("2") 45 | .engine(engine) 46 | .operator(operator2) 47 | ; 48 | 49 | engine.runAndWait(9000); 50 | if (engine.getEx() != null) { 51 | engine.getEx().printStackTrace(); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/callback/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.callback; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator1 implements IOperator { 12 | 13 | @Override 14 | public Integer execute(Void param) throws Exception { 15 | System.out.println("1..."); 16 | TimeUnit.SECONDS.sleep(1); 17 | return 1; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/callback/Operator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.callback; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator2 implements IOperator { 12 | 13 | @Override 14 | public Integer execute(Void param) throws Exception { 15 | System.out.println("2..."); 16 | TimeUnit.SECONDS.sleep(1); 17 | return 1; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/branch/ChooseBranchTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.branch; 2 | 3 | import com.google.common.collect.Sets; 4 | import org.taskflow.core.DagEngine; 5 | import org.taskflow.core.thread.pool.CustomThreadPool; 6 | import org.taskflow.core.wrapper.OperatorWrapper; 7 | import org.junit.Test; 8 | 9 | import java.util.concurrent.ExecutorService; 10 | 11 | /** 12 | * 分支选择 13 | * Created by ytyht226 on 2022/6/23. 14 | */ 15 | @SuppressWarnings("all") 16 | public class ChooseBranchTest { 17 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 18 | Operator1 operator1 = new Operator1(); 19 | Operator2 operator2 = new Operator2(); 20 | Operator3 operator3 = new Operator3(); 21 | Operator4 operator4 = new Operator4(); 22 | Operator5 operator5 = new Operator5(); 23 | Operator6 operator6 = new Operator6(); 24 | 25 | @Test 26 | public void test() { 27 | DagEngine engine = new DagEngine(executor); 28 | OperatorWrapper wrapper1 = new OperatorWrapper() 29 | .id("1") 30 | .engine(engine) 31 | .operator(operator1) 32 | .chooseBranch((w) -> { 33 | return Sets.newHashSet("2"); 34 | }) 35 | ; 36 | OperatorWrapper wrapper2 = new OperatorWrapper() 37 | .id("2") 38 | .engine(engine) 39 | .operator(operator2) 40 | .depend("1") 41 | ; 42 | OperatorWrapper wrapper3 = new OperatorWrapper() 43 | .id("3") 44 | .engine(engine) 45 | .operator(operator3) 46 | .depend("1") 47 | ; 48 | OperatorWrapper wrapper4 = new OperatorWrapper() 49 | .id("4") 50 | .engine(engine) 51 | .operator(operator4) 52 | .depend("1") 53 | ; 54 | OperatorWrapper wrapper5 = new OperatorWrapper() 55 | .id("5") 56 | .engine(engine) 57 | .operator(operator5) 58 | .depend("2") 59 | ; 60 | OperatorWrapper wrapper6 = new OperatorWrapper() 61 | .id("6") 62 | .engine(engine) 63 | .operator(operator6) 64 | .depend("2") 65 | ; 66 | 67 | engine.runAndWait(300_000); 68 | if (engine.getEx() != null) { 69 | engine.getEx().printStackTrace(); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/branch/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.branch; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator1 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("1..."); 14 | return 3; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/branch/Operator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.branch; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator2 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("2..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/branch/Operator3.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.branch; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator3 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("3..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/branch/Operator4.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.branch; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator4 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("4..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/branch/Operator5.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.branch; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator5 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("5..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/branch/Operator6.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.branch; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator6 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("6..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/group_group/ChooseOpTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.group_group; 2 | 3 | import com.google.common.collect.Sets; 4 | import org.taskflow.core.DagEngine; 5 | import org.taskflow.core.thread.pool.CustomThreadPool; 6 | import org.taskflow.core.wrapper.OperatorWrapper; 7 | import org.taskflow.core.wrapper.OperatorWrapperGroup; 8 | import org.junit.Test; 9 | 10 | import java.util.concurrent.ExecutorService; 11 | 12 | /** 13 | * 节点选择 14 | * 待选择的都是节点组 15 | * Created by ytyht226 on 2022/6/23. 16 | */ 17 | @SuppressWarnings("all") 18 | public class ChooseOpTest { 19 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 20 | Operator1 operator1 = new Operator1(); 21 | Operator2 operator2 = new Operator2(); 22 | Operator3 operator3 = new Operator3(); 23 | Operator4 operator4 = new Operator4(); 24 | Operator5 operator5 = new Operator5(); 25 | Operator6 operator6 = new Operator6(); 26 | 27 | @Test 28 | public void test() { 29 | DagEngine engine = new DagEngine(executor); 30 | 31 | //节点2、4是一个节点组 32 | OperatorWrapperGroup group1 = buildGroup1(engine); 33 | //节点3、5是一个节点组 34 | OperatorWrapperGroup group2 = buildGroup2(engine); 35 | 36 | OperatorWrapper wrapper1 = new OperatorWrapper() 37 | .id("1") 38 | .engine(engine) 39 | .operator(operator1) 40 | .next(group1.getGroupBeginId()) 41 | .next(group2.getGroupBeginId()) 42 | .chooseOp(wrapper -> { 43 | //节点组1、2都执行 44 | return Sets.newHashSet(group1.getGroupBeginId(), group2.getGroupBeginId()); 45 | }) 46 | ; 47 | 48 | group1.next("6"); 49 | group2.next("6"); 50 | 51 | OperatorWrapper wrapper6 = new OperatorWrapper() 52 | .id("6") 53 | .engine(engine) 54 | .operator(operator6) 55 | ; 56 | 57 | engine.runAndWait(300_000); 58 | if (engine.getEx() != null) { 59 | engine.getEx().printStackTrace(); 60 | } 61 | } 62 | 63 | private OperatorWrapperGroup buildGroup1(DagEngine engine) { 64 | OperatorWrapper wrapper2 = new OperatorWrapper() 65 | .id("2") 66 | .engine(engine) 67 | .operator(operator2) 68 | .next("4") 69 | ; 70 | OperatorWrapper wrapper3 = new OperatorWrapper() 71 | .id("4") 72 | .engine(engine) 73 | .operator(operator4) 74 | ; 75 | 76 | return new OperatorWrapperGroup(engine) 77 | .beginWrapperIds("2") 78 | .endWrapperIds("4") 79 | .children("2", "4") 80 | .init() 81 | ; 82 | } 83 | 84 | private OperatorWrapperGroup buildGroup2(DagEngine engine) { 85 | OperatorWrapper wrapper3 = new OperatorWrapper() 86 | .id("3") 87 | .engine(engine) 88 | .operator(operator3) 89 | .next("5") 90 | ; 91 | OperatorWrapper wrapper5 = new OperatorWrapper() 92 | .id("5") 93 | .engine(engine) 94 | .operator(operator5) 95 | ; 96 | 97 | return new OperatorWrapperGroup(engine) 98 | .beginWrapperIds("3") 99 | .endWrapperIds("5") 100 | .children("3", "5") 101 | .init() 102 | ; 103 | } 104 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/group_group/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.group_group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator1 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("1..."); 14 | return 3; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/group_group/Operator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.group_group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator2 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("2..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/group_group/Operator3.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.group_group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator3 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("3..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/group_group/Operator4.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.group_group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator4 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("4..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/group_group/Operator5.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.group_group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator5 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("5..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/group_group/Operator6.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.group_group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator6 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("6..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/group_op/ChooseOpTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.group_op; 2 | 3 | import com.google.common.collect.Sets; 4 | import org.taskflow.core.DagEngine; 5 | import org.taskflow.core.thread.pool.CustomThreadPool; 6 | import org.taskflow.core.wrapper.OperatorWrapper; 7 | import org.taskflow.core.wrapper.OperatorWrapperGroup; 8 | import org.junit.Test; 9 | 10 | import java.util.concurrent.ExecutorService; 11 | 12 | /** 13 | * 节点选择 14 | * 待选择的是节点、节点组 15 | * Created by ytyht226 on 2022/6/23. 16 | */ 17 | @SuppressWarnings("all") 18 | public class ChooseOpTest { 19 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 20 | Operator1 operator1 = new Operator1(); 21 | Operator2 operator2 = new Operator2(); 22 | Operator3 operator3 = new Operator3(); 23 | Operator4 operator4 = new Operator4(); 24 | Operator5 operator5 = new Operator5(); 25 | 26 | @Test 27 | public void test() { 28 | DagEngine engine = new DagEngine(executor); 29 | 30 | //节点2、4是一个节点组 31 | OperatorWrapperGroup group1 = buildGroup1(engine); 32 | 33 | OperatorWrapper wrapper1 = new OperatorWrapper() 34 | .id("1") 35 | .engine(engine) 36 | .operator(operator1) 37 | .next(group1.getGroupBeginId()) 38 | .next("3") 39 | .chooseOp(wrapper -> { 40 | //执行节点组1 41 | return Sets.newHashSet(group1.getGroupBeginId()); 42 | }) 43 | ; 44 | 45 | group1.next("5"); 46 | 47 | OperatorWrapper wrapper3 = new OperatorWrapper() 48 | .id("3") 49 | .engine(engine) 50 | .operator(operator3) 51 | .next("5") 52 | ; 53 | OperatorWrapper wrapper4 = new OperatorWrapper() 54 | .id("5") 55 | .engine(engine) 56 | .operator(operator5) 57 | ; 58 | 59 | engine.runAndWait(300_000); 60 | if (engine.getEx() != null) { 61 | engine.getEx().printStackTrace(); 62 | } 63 | } 64 | 65 | private OperatorWrapperGroup buildGroup1(DagEngine engine) { 66 | OperatorWrapper wrapper2 = new OperatorWrapper() 67 | .id("2") 68 | .engine(engine) 69 | .operator(operator2) 70 | .next("4") 71 | ; 72 | OperatorWrapper wrapper3 = new OperatorWrapper() 73 | .id("4") 74 | .engine(engine) 75 | .operator(operator4) 76 | ; 77 | 78 | return new OperatorWrapperGroup(engine) 79 | .beginWrapperIds("2") 80 | .endWrapperIds("4") 81 | .children("2", "4") 82 | .init() 83 | ; 84 | } 85 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/group_op/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.group_op; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator1 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("1..."); 14 | return 3; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/group_op/Operator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.group_op; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator2 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("2..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/group_op/Operator3.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.group_op; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator3 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("3..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/group_op/Operator4.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.group_op; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator4 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("4..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/group_op/Operator5.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.group_op; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator5 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("5..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/nest_group/ChooseOpTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.nest_group; 2 | 3 | import com.google.common.collect.Sets; 4 | import org.taskflow.core.DagEngine; 5 | import org.taskflow.core.thread.pool.CustomThreadPool; 6 | import org.taskflow.core.wrapper.OperatorWrapper; 7 | import org.taskflow.core.wrapper.OperatorWrapperGroup; 8 | import org.junit.Test; 9 | 10 | import java.util.concurrent.ExecutorService; 11 | 12 | /** 13 | * 节点选择 14 | * 待选择的都是节点组 15 | * Created by ytyht226 on 2022/6/23. 16 | */ 17 | @SuppressWarnings("all") 18 | public class ChooseOpTest { 19 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 20 | Operator1 operator1 = new Operator1(); 21 | Operator2 operator2 = new Operator2(); 22 | Operator3 operator3 = new Operator3(); 23 | Operator4 operator4 = new Operator4(); 24 | Operator5 operator5 = new Operator5(); 25 | Operator6 operator6 = new Operator6(); 26 | Operator7 operator7 = new Operator7(); 27 | Operator8 operator8 = new Operator8(); 28 | Operator9 operator9 = new Operator9(); 29 | 30 | @Test 31 | public void test() { 32 | DagEngine engine = new DagEngine(executor); 33 | 34 | //节点2、4是一个节点组 35 | OperatorWrapperGroup group1 = buildGroup1(engine); 36 | //节点3、5是一个节点组 37 | OperatorWrapperGroup group2 = buildGroup2(engine); 38 | //节点1、节点组group1、group2是一个节点组 39 | OperatorWrapperGroup group3 = buildGroup3(engine, group1, group2); 40 | 41 | OperatorWrapper wrapper7 = new OperatorWrapper() 42 | .id("7") 43 | .engine(engine) 44 | .operator(operator7) 45 | .next(group3.getGroupBeginId()) 46 | .next("8") 47 | .chooseOp(wrapper -> { 48 | 49 | return Sets.newHashSet(group3.getGroupBeginId()); 50 | // return Sets.newHashSet("8"); 51 | }) 52 | ; 53 | 54 | group3.next("9"); 55 | 56 | OperatorWrapper wrapper8 = new OperatorWrapper() 57 | .id("8") 58 | .engine(engine) 59 | .operator(operator8) 60 | .next("9") 61 | ; 62 | 63 | OperatorWrapper wrapper9 = new OperatorWrapper() 64 | .id("9") 65 | .engine(engine) 66 | .operator(operator9) 67 | ; 68 | 69 | engine.runAndWait(300_000); 70 | if (engine.getEx() != null) { 71 | engine.getEx().printStackTrace(); 72 | } 73 | } 74 | 75 | private OperatorWrapperGroup buildGroup1(DagEngine engine) { 76 | OperatorWrapper wrapper2 = new OperatorWrapper() 77 | .id("2") 78 | .engine(engine) 79 | .operator(operator2) 80 | .next("4") 81 | ; 82 | OperatorWrapper wrapper3 = new OperatorWrapper() 83 | .id("4") 84 | .engine(engine) 85 | .operator(operator4) 86 | ; 87 | 88 | return new OperatorWrapperGroup(engine) 89 | .beginWrapperIds("2") 90 | .endWrapperIds("4") 91 | .children("2", "4") 92 | .init() 93 | ; 94 | } 95 | 96 | private OperatorWrapperGroup buildGroup2(DagEngine engine) { 97 | OperatorWrapper wrapper3 = new OperatorWrapper() 98 | .id("3") 99 | .engine(engine) 100 | .operator(operator3) 101 | .next("5") 102 | ; 103 | OperatorWrapper wrapper5 = new OperatorWrapper() 104 | .id("5") 105 | .engine(engine) 106 | .operator(operator5) 107 | ; 108 | 109 | return new OperatorWrapperGroup(engine) 110 | .beginWrapperIds("3") 111 | .endWrapperIds("5") 112 | .children("3", "5") 113 | .init() 114 | ; 115 | } 116 | 117 | private OperatorWrapperGroup buildGroup3(DagEngine engine, OperatorWrapperGroup group1, OperatorWrapperGroup group2) { 118 | OperatorWrapper wrapper1 = new OperatorWrapper() 119 | .id("1") 120 | .engine(engine) 121 | .operator(operator1) 122 | .chooseOp(wrapper -> { 123 | 124 | return Sets.newHashSet(group1.getGroupBeginId()); 125 | // return Sets.newHashSet(group2.getGroupBeginId()); 126 | }) 127 | .next(group1.getGroupBeginId(), group2.getGroupBeginId()) 128 | ; 129 | 130 | group1.next("6"); 131 | group2.next("6"); 132 | 133 | OperatorWrapper wrapper6 = new OperatorWrapper() 134 | .id("6") 135 | .engine(engine) 136 | .operator(operator6) 137 | ; 138 | 139 | return new OperatorWrapperGroup(engine) 140 | .beginWrapperIds("1") 141 | .endWrapperIds("6") 142 | .init() 143 | ; 144 | } 145 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/nest_group/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.nest_group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator1 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("1..."); 14 | return 3; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/nest_group/Operator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.nest_group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator2 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("2..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/nest_group/Operator3.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.nest_group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator3 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("3..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/nest_group/Operator4.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.nest_group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator4 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | //业务逻辑部分 15 | TimeUnit.MILLISECONDS.sleep(1000); 16 | System.out.println("4..."); 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/nest_group/Operator5.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.nest_group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator5 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | //业务逻辑部分 15 | TimeUnit.MILLISECONDS.sleep(1000); 16 | System.out.println("5..."); 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/nest_group/Operator6.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.nest_group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator6 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | //业务逻辑部分 15 | TimeUnit.MILLISECONDS.sleep(1000); 16 | System.out.println("6..."); 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/nest_group/Operator7.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.nest_group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator7 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("7..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/nest_group/Operator8.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.nest_group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator8 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("8..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/nest_group/Operator9.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.nest_group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator9 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("9..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/op_op/ChooseOpTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.op_op; 2 | 3 | import com.google.common.collect.Sets; 4 | import org.taskflow.core.DagEngine; 5 | import org.taskflow.core.thread.pool.CustomThreadPool; 6 | import org.taskflow.core.wrapper.OperatorWrapper; 7 | import org.junit.Test; 8 | 9 | import java.util.concurrent.ExecutorService; 10 | 11 | /** 12 | * 节点选择 13 | * 待选择的都是节点 14 | * Created by ytyht226 on 2022/6/23. 15 | */ 16 | @SuppressWarnings("all") 17 | public class ChooseOpTest { 18 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 19 | Operator1 operator1 = new Operator1(); 20 | Operator2 operator2 = new Operator2(); 21 | Operator3 operator3 = new Operator3(); 22 | Operator4 operator4 = new Operator4(); 23 | 24 | @Test 25 | public void test() { 26 | DagEngine engine = new DagEngine(executor); 27 | OperatorWrapper wrapper1 = new OperatorWrapper() 28 | .id("1") 29 | .engine(engine) 30 | .operator(operator1) 31 | .next("2", "3") 32 | .chooseOp((w) -> { 33 | return Sets.newHashSet("3"); 34 | }); 35 | OperatorWrapper wrapper2 = new OperatorWrapper() 36 | .id("2") 37 | .engine(engine) 38 | .operator(operator2) 39 | .next("4") 40 | ; 41 | OperatorWrapper wrapper3 = new OperatorWrapper() 42 | .id("3") 43 | .engine(engine) 44 | .operator(operator3) 45 | .next("4") 46 | ; 47 | OperatorWrapper wrapper4 = new OperatorWrapper() 48 | .id("4") 49 | .engine(engine) 50 | .operator(operator4) 51 | ; 52 | 53 | engine.runAndWait(300_000); 54 | if (engine.getEx() != null) { 55 | engine.getEx().printStackTrace(); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/op_op/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.op_op; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator1 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("1..."); 14 | return 3; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/op_op/Operator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.op_op; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator2 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("2..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/op_op/Operator3.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.op_op; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator3 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("3..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/choose/op/op_op/Operator4.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.choose.op.op_op; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator4 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("4..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/condition/ConditionTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.condition; 2 | 3 | import org.junit.Test; 4 | import org.taskflow.core.DagContextHolder; 5 | import org.taskflow.core.DagEngine; 6 | import org.taskflow.core.callback.ICondition; 7 | import org.taskflow.core.enums.ResultState; 8 | import org.taskflow.core.operator.OperatorResult; 9 | import org.taskflow.core.thread.pool.CustomThreadPool; 10 | import org.taskflow.core.wrapper.OperatorWrapper; 11 | 12 | import java.util.List; 13 | import java.util.concurrent.ExecutorService; 14 | 15 | /** 16 | * 准入条件判断 17 | * Created by ytyht226 on 2022/3/17. 18 | */ 19 | @SuppressWarnings("all") 20 | public class ConditionTest { 21 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 22 | Operator1 operator1 = new Operator1(); 23 | Operator2 operator2 = new Operator2(); 24 | Operator3 operator3 = new Operator3(); 25 | Operator4 operator4 = new Operator4(); 26 | Operator5 operator5 = new Operator5(); 27 | 28 | @Test 29 | public void test100() { 30 | for (int i = 0; i < 100; i++) { 31 | test(); 32 | } 33 | } 34 | 35 | @Test 36 | public void test() { 37 | DagEngine engine = new DagEngine(executor); 38 | int param = 1; 39 | OperatorWrapper wrapper1 = new OperatorWrapper() 40 | .id("1") 41 | .engine(engine) 42 | .operator(operator1) 43 | .context(param) 44 | ; 45 | OperatorWrapper wrapper2 = new OperatorWrapper() 46 | .id("2") 47 | .engine(engine) 48 | .operator(operator2) 49 | .addParamFromWrapperId("1") 50 | ; 51 | OperatorWrapper wrapper3 = new OperatorWrapper() 52 | .id("3") 53 | .engine(engine) 54 | .operator(operator3) 55 | .addParamFromWrapperId("1") 56 | ; 57 | OperatorWrapper wrapper4 = new OperatorWrapper() 58 | .id("4") 59 | .engine(engine) 60 | .operator(operator4) 61 | .addParamFromWrapperId("1") 62 | ; 63 | OperatorWrapper, Integer> wrapper5 = new OperatorWrapper, Integer>() 64 | .id("5") 65 | .engine(engine) 66 | .operator(operator5) 67 | .addParamFromWrapperId("2", "3", "4") 68 | .depend("2", false) 69 | .depend("3", false) 70 | .depend("4", false) 71 | .condition(new Wrapper5Condition()) 72 | ; 73 | 74 | long begin = System.currentTimeMillis(); 75 | engine.runAndWait(900_000); 76 | long end = System.currentTimeMillis(); 77 | System.out.println("result: " + wrapper5.getOperatorResult().getResult() + ", cost: " + (end - begin)); 78 | if (engine.getEx() != null) { 79 | engine.getEx().printStackTrace(); 80 | } 81 | } 82 | 83 | /** 84 | * 节点5根据 2、3、4的执行情况判断是否执行该节点 85 | */ 86 | private static class Wrapper5Condition implements ICondition { 87 | 88 | @Override 89 | public boolean judge(OperatorWrapper wrapper) { 90 | OperatorResult wrapper2Result = DagContextHolder.getOperatorResult("2"); 91 | OperatorResult wrapper3Result = DagContextHolder.getOperatorResult("3"); 92 | OperatorResult wrapper4Result = DagContextHolder.getOperatorResult("4"); 93 | int result = 0; 94 | if (wrapper2Result != null && wrapper2Result.getResultState() == ResultState.SUCCESS) { 95 | result = result + wrapper2Result.getResult(); 96 | } 97 | if (wrapper3Result != null && wrapper3Result.getResultState() == ResultState.SUCCESS) { 98 | result = result + wrapper3Result.getResult(); 99 | } 100 | if (wrapper4Result != null && wrapper4Result.getResultState() == ResultState.SUCCESS) { 101 | result = result + wrapper4Result.getResult(); 102 | } 103 | System.out.println("Current result: " + result); 104 | //如果result >= 5,则返回 true,可以直接执行节点5,因为节点2、4都是sleep(10),节点3 sleep(100) 105 | //result(2)+result(4)=6 > 5,执行完节点2、4后就可以执行节点5,此时节点3还在执行中会被中断,最终的 106 | //执行路径为 1 -> (2,4) -> 5 107 | return result >= 5; 108 | } 109 | } 110 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/condition/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.condition; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/4/1. 10 | */ 11 | public class Operator1 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | TimeUnit.MILLISECONDS.sleep(10); 15 | return param; 16 | } 17 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/condition/Operator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.condition; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/4/1. 10 | */ 11 | public class Operator2 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | TimeUnit.MILLISECONDS.sleep(10); 15 | return param * 2; 16 | } 17 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/condition/Operator3.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.condition; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/4/1. 10 | */ 11 | public class Operator3 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | TimeUnit.MILLISECONDS.sleep(10); 15 | return param * 3; 16 | } 17 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/condition/Operator4.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.condition; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/4/1. 10 | */ 11 | public class Operator4 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | TimeUnit.MILLISECONDS.sleep(10); 15 | return param * 4; 16 | } 17 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/condition/Operator5.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.condition; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.List; 7 | import java.util.concurrent.TimeUnit; 8 | 9 | /** 10 | * Created by ytyht226 on 2022/4/1. 11 | */ 12 | public class Operator5 implements IOperator, Integer> { 13 | @Override 14 | public Integer execute(List param) throws Exception { 15 | TimeUnit.MILLISECONDS.sleep(10); 16 | int sum = 0; 17 | for (Integer i : param) { 18 | if (i != null) { 19 | sum += i; 20 | } 21 | } 22 | return sum; 23 | } 24 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/context/ContextTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.context; 2 | 3 | import org.taskflow.core.DagEngine; 4 | import org.taskflow.core.thread.pool.CustomThreadPool; 5 | import org.taskflow.core.wrapper.OperatorWrapper; 6 | import org.junit.Test; 7 | 8 | import java.util.concurrent.ExecutorService; 9 | 10 | /** 11 | * 全局上下文 12 | * Created by ytyht226 on 2022/6/23. 13 | */ 14 | public class ContextTest { 15 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 16 | Operator1 operator1 = new Operator1(); 17 | Operator2 operator2 = new Operator2(); 18 | 19 | @Test 20 | public void test() { 21 | DagEngine engine = new DagEngine(executor); 22 | OperatorWrapper wrapper1 = new OperatorWrapper() 23 | .id("1") 24 | .engine(engine) 25 | .operator(operator1) 26 | ; 27 | OperatorWrapper wrapper2 = new OperatorWrapper() 28 | .id("2") 29 | .engine(engine) 30 | .operator(operator2) 31 | .depend("1") 32 | ; 33 | engine.runAndWait(9000); 34 | if (engine.getEx() != null) { 35 | engine.getEx().printStackTrace(); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/context/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.context; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator1 implements IOperator { 12 | 13 | @Override 14 | public Integer execute(Void param) throws Exception { 15 | System.out.println("1..."); 16 | TimeUnit.SECONDS.sleep(1); 17 | return 1; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/context/Operator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.context; 2 | 3 | 4 | import org.taskflow.core.DagContextHolder; 5 | import org.taskflow.core.operator.IOperator; 6 | 7 | /** 8 | * Created by ytyht226 on 2022/6/23. 9 | */ 10 | public class Operator2 implements IOperator { 11 | @Override 12 | public Integer execute(Void param) throws Exception { 13 | //业务逻辑部分 14 | System.out.println(DagContextHolder.getOperatorResult("1")); 15 | System.out.println("2..."); 16 | return 2; 17 | } 18 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/dependencytype/DependencyTypeTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.dependencytype; 2 | 3 | import org.taskflow.core.DagEngine; 4 | import org.taskflow.core.thread.pool.CustomThreadPool; 5 | import org.taskflow.core.wrapper.OperatorWrapper; 6 | import org.junit.Test; 7 | 8 | import java.util.concurrent.ExecutorService; 9 | 10 | /** 11 | * 节点依赖类型 强依赖、弱依赖 12 | * Created by ytyht226 on 2022/6/23. 13 | */ 14 | @SuppressWarnings("all") 15 | public class DependencyTypeTest { 16 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 17 | Operator1 operator1 = new Operator1(); 18 | Operator2 operator2 = new Operator2(); 19 | Operator3 operator3 = new Operator3(); 20 | Operator4 operator4 = new Operator4(); 21 | 22 | /** 23 | * 强依赖 24 | */ 25 | @Test 26 | public void strongTypeTest() { 27 | DagEngine engine = new DagEngine(executor); 28 | OperatorWrapper wrapper1 = new OperatorWrapper() 29 | .id("1") 30 | .engine(engine) 31 | .operator(operator1) 32 | .next("2", "3") 33 | ; 34 | OperatorWrapper wrapper2 = new OperatorWrapper() 35 | .id("2") 36 | .engine(engine) 37 | .operator(operator2) 38 | .next("4") 39 | ; 40 | OperatorWrapper wrapper3 = new OperatorWrapper() 41 | .id("3") 42 | .engine(engine) 43 | .operator(operator3) 44 | .next("4") 45 | ; 46 | 47 | OperatorWrapper wrapper4 = new OperatorWrapper() 48 | .id("4") 49 | .engine(engine) 50 | .operator(operator4) 51 | ; 52 | 53 | engine.runAndWait(3000); 54 | if (engine.getEx() != null) { 55 | engine.getEx().printStackTrace(); 56 | } 57 | } 58 | 59 | /** 60 | * 弱依赖 61 | * 节点4弱依赖2、3,只要2、3 中有任意一个执行完,就可以执行节点4 62 | */ 63 | @Test 64 | public void weakTypeTest() { 65 | DagEngine engine = new DagEngine(executor); 66 | OperatorWrapper wrapper1 = new OperatorWrapper() 67 | .id("1") 68 | .engine(engine) 69 | .operator(operator1) 70 | .next("2", "3") 71 | ; 72 | OperatorWrapper wrapper2 = new OperatorWrapper() 73 | .id("2") 74 | .engine(engine) 75 | .operator(operator2) 76 | .next("4", false) 77 | ; 78 | OperatorWrapper wrapper3 = new OperatorWrapper() 79 | .id("3") 80 | .engine(engine) 81 | .operator(operator3) 82 | .next("4", false) 83 | ; 84 | 85 | OperatorWrapper wrapper4 = new OperatorWrapper() 86 | .id("4") 87 | .engine(engine) 88 | .operator(operator4) 89 | ; 90 | 91 | engine.runAndWait(3000); 92 | 93 | if (engine.getEx() != null) { 94 | engine.getEx().printStackTrace(); 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/dependencytype/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.dependencytype; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator1 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | //业务逻辑部分 15 | TimeUnit.MILLISECONDS.sleep(100); 16 | System.out.println("1..."); 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/dependencytype/Operator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.dependencytype; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator2 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | //业务逻辑部分 15 | TimeUnit.MILLISECONDS.sleep(100); 16 | System.out.println("2..."); 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/dependencytype/Operator3.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.dependencytype; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator3 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | //业务逻辑部分 15 | TimeUnit.MILLISECONDS.sleep(300); 16 | System.out.println("3..."); 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/dependencytype/Operator4.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.dependencytype; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator4 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("4..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/endpoint/EndpointTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.endpoint; 2 | 3 | import org.taskflow.core.DagEngine; 4 | import org.taskflow.core.thread.pool.CustomThreadPool; 5 | import org.taskflow.core.wrapper.OperatorWrapper; 6 | import org.junit.Test; 7 | 8 | import java.util.concurrent.ExecutorService; 9 | 10 | /** 11 | * 自定义流程中断 12 | * Created by ytyht226 on 2022/6/23. 13 | */ 14 | @SuppressWarnings("all") 15 | public class EndpointTest { 16 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 17 | Operator1 operator1 = new Operator1(); 18 | Operator2 operator2 = new Operator2(); 19 | Operator3 operator3 = new Operator3(); 20 | Operator4 operator4 = new Operator4(); 21 | 22 | @Test 23 | public void test() throws InterruptedException { 24 | DagEngine engine = new DagEngine(executor); 25 | OperatorWrapper wrapper1 = new OperatorWrapper() 26 | .id("1") 27 | .engine(engine) 28 | .operator(operator1) 29 | .next("2") 30 | ; 31 | OperatorWrapper wrapper2 = new OperatorWrapper() 32 | .id("2") 33 | .engine(engine) 34 | .operator(operator2) 35 | .next("3") 36 | .next("4") 37 | .after((w) -> { 38 | //设置结束节点 39 | w.getEngine().stopAt("3"); 40 | }) 41 | ; 42 | OperatorWrapper wrapper3 = new OperatorWrapper() 43 | .id("3") 44 | .engine(engine) 45 | .operator(operator3) 46 | ; 47 | 48 | OperatorWrapper wrapper4 = new OperatorWrapper() 49 | .id("4") 50 | .engine(engine) 51 | .operator(operator4) 52 | ; 53 | 54 | engine.runAndWait(300_000); 55 | 56 | if (engine.getEx() != null) { 57 | engine.getEx().printStackTrace(); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/endpoint/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.endpoint; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator1 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("1..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/endpoint/Operator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.endpoint; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator2 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("2..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/endpoint/Operator3.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.endpoint; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator3 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | //业务逻辑部分 15 | TimeUnit.MILLISECONDS.sleep(10); 16 | System.out.println("3..."); 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/endpoint/Operator4.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.endpoint; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator4 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | //业务逻辑部分 15 | TimeUnit.MILLISECONDS.sleep(100); 16 | System.out.println("4..."); 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/GroupTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group; 2 | 3 | import org.taskflow.core.DagEngine; 4 | import org.taskflow.core.thread.pool.CustomThreadPool; 5 | import org.taskflow.core.wrapper.OperatorWrapper; 6 | import org.taskflow.core.wrapper.OperatorWrapperGroup; 7 | import org.junit.Test; 8 | 9 | import java.util.concurrent.ExecutorService; 10 | 11 | /** 12 | * 节点组 13 | * Created by ytyht226 on 2022/6/23. 14 | */ 15 | @SuppressWarnings("all") 16 | public class GroupTest { 17 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 18 | Operator1 operator1 = new Operator1(); 19 | Operator2 operator2 = new Operator2(); 20 | Operator3 operator3 = new Operator3(); 21 | Operator4 operator4 = new Operator4(); 22 | Operator5 operator5 = new Operator5(); 23 | Operator6 operator6 = new Operator6(); 24 | Operator7 operator7 = new Operator7(); 25 | Operator8 operator8 = new Operator8(); 26 | Operator9 operator9 = new Operator9(); 27 | Operator10 operator10 = new Operator10(); 28 | 29 | @Test 30 | public void test() { 31 | DagEngine engine = new DagEngine(executor); 32 | //节点1、2、3、4是一个节点组 33 | OperatorWrapperGroup group1 = buildGroup1(engine); 34 | //节点5、6、7、8是一个节点组 35 | OperatorWrapperGroup group2 = buildGroup2(engine); 36 | //节点组1的后继节点是节点组2的开始节点 37 | group1.next(group2.getGroupBeginId()); 38 | //节点组2(结束节点)的后继节点是节点9 39 | group2.next("9"); 40 | 41 | OperatorWrapper wrapper9 = new OperatorWrapper() 42 | .id("9") 43 | .engine(engine) 44 | .operator(operator9) 45 | //节点9的后继节点是节点10 46 | .next("10") 47 | ; 48 | OperatorWrapper wrapper10 = new OperatorWrapper() 49 | .id("10") 50 | .engine(engine) 51 | .operator(operator10) 52 | ; 53 | engine.runAndWait(300_000); 54 | if (engine.getEx() != null) { 55 | engine.getEx().printStackTrace(); 56 | } 57 | } 58 | 59 | private OperatorWrapperGroup buildGroup1(DagEngine engine) { 60 | OperatorWrapper wrapper1 = new OperatorWrapper() 61 | .id("1") 62 | .engine(engine) 63 | .operator(operator1) 64 | ; 65 | OperatorWrapper wrapper2 = new OperatorWrapper() 66 | .id("2") 67 | .engine(engine) 68 | .operator(operator2) 69 | .depend("1") 70 | ; 71 | OperatorWrapper wrapper3 = new OperatorWrapper() 72 | .id("3") 73 | .engine(engine) 74 | .operator(operator3) 75 | .depend("1") 76 | ; 77 | OperatorWrapper wrapper4 = new OperatorWrapper() 78 | .id("4") 79 | .engine(engine) 80 | .operator(operator4) 81 | .depend("1") 82 | ; 83 | 84 | return new OperatorWrapperGroup(engine) 85 | .beginWrapperIds("1") 86 | .endWrapperIds("2", "3", "4") 87 | .init() 88 | ; 89 | } 90 | 91 | private OperatorWrapperGroup buildGroup2(DagEngine engine) { 92 | OperatorWrapper wrapper5 = new OperatorWrapper() 93 | .id("5") 94 | .engine(engine) 95 | .operator(operator5) 96 | ; 97 | OperatorWrapper wrapper6 = new OperatorWrapper() 98 | .id("6") 99 | .engine(engine) 100 | .operator(operator6) 101 | .depend("5") 102 | ; 103 | OperatorWrapper wrapper7 = new OperatorWrapper() 104 | .id("7") 105 | .engine(engine) 106 | .operator(operator7) 107 | .depend("5") 108 | ; 109 | OperatorWrapper wrapper8 = new OperatorWrapper() 110 | .id("8") 111 | .engine(engine) 112 | .operator(operator8) 113 | .depend("5") 114 | ; 115 | 116 | return new OperatorWrapperGroup(engine) 117 | .beginWrapperIds("5") 118 | .endWrapperIds("6", "7", "8") 119 | .init() 120 | ; 121 | } 122 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator1 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("1..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/Operator10.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator10 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("10..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/Operator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator2 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("2..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/Operator3.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator3 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("3..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/Operator4.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator4 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("4..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/Operator5.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator5 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | //业务逻辑部分 15 | TimeUnit.MILLISECONDS.sleep(1000); 16 | System.out.println("5..."); 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/Operator6.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator6 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("6..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/Operator7.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator7 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("7..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/Operator8.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator8 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("8..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/Operator9.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator9 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | //业务逻辑部分 15 | TimeUnit.MILLISECONDS.sleep(1000); 16 | System.out.println("9..."); 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/nest/GroupTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group.nest; 2 | 3 | import org.taskflow.core.DagEngine; 4 | import org.taskflow.core.thread.pool.CustomThreadPool; 5 | import org.taskflow.core.wrapper.OperatorWrapper; 6 | import org.taskflow.core.wrapper.OperatorWrapperGroup; 7 | import org.junit.Test; 8 | 9 | import java.util.concurrent.ExecutorService; 10 | 11 | /** 12 | * 嵌套节点组 13 | * Created by ytyht226 on 2022/6/23. 14 | */ 15 | @SuppressWarnings("all") 16 | public class GroupTest { 17 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 18 | Operator1 operator1 = new Operator1(); 19 | Operator2 operator2 = new Operator2(); 20 | Operator3 operator3 = new Operator3(); 21 | Operator4 operator4 = new Operator4(); 22 | Operator5 operator5 = new Operator5(); 23 | Operator6 operator6 = new Operator6(); 24 | Operator7 operator7 = new Operator7(); 25 | Operator8 operator8 = new Operator8(); 26 | Operator9 operator9 = new Operator9(); 27 | 28 | @Test 29 | public void test() { 30 | DagEngine engine = new DagEngine(executor); 31 | //节点2、3、4、5是节点组 group1 32 | OperatorWrapperGroup group1 = buildGroup1(engine); 33 | //节点6、7是节点组 group2 34 | OperatorWrapperGroup group2 = buildGroup2(engine); 35 | //节点组 group1、group2 和 节点8是节点组 group3 36 | OperatorWrapperGroup group3 = buildGroup3(engine, group1, group2); 37 | 38 | //节点1的后继节点是节点组group3 39 | OperatorWrapper wrapper1 = new OperatorWrapper() 40 | .id("1") 41 | .engine(engine) 42 | .operator(operator1) 43 | .next(group3.getGroupBeginId()) 44 | ; 45 | //节点组3的后继节点是节点9 46 | group3.next("9"); 47 | 48 | OperatorWrapper wrapper9 = new OperatorWrapper() 49 | .id("9") 50 | .engine(engine) 51 | .operator(operator9) 52 | ; 53 | engine.runAndWait(300_000); 54 | if (engine.getEx() != null) { 55 | engine.getEx().printStackTrace(); 56 | } 57 | } 58 | 59 | private OperatorWrapperGroup buildGroup1(DagEngine engine) { 60 | 61 | OperatorWrapper wrapper2 = new OperatorWrapper() 62 | .id("2") 63 | .engine(engine) 64 | .operator(operator2) 65 | ; 66 | OperatorWrapper wrapper3 = new OperatorWrapper() 67 | .id("3") 68 | .engine(engine) 69 | .operator(operator3) 70 | .depend("2") 71 | ; 72 | OperatorWrapper wrapper4 = new OperatorWrapper() 73 | .id("4") 74 | .engine(engine) 75 | .operator(operator4) 76 | .depend("2") 77 | ; 78 | OperatorWrapper wrapper5 = new OperatorWrapper() 79 | .id("5") 80 | .engine(engine) 81 | .operator(operator5) 82 | .depend("3", "4") 83 | ; 84 | 85 | return new OperatorWrapperGroup(engine) 86 | .beginWrapperIds("2") 87 | .endWrapperIds("5") 88 | .children("2", "3", "4", "5") 89 | .init() 90 | ; 91 | } 92 | 93 | private OperatorWrapperGroup buildGroup2(DagEngine engine) { 94 | OperatorWrapper wrapper6 = new OperatorWrapper() 95 | .id("6") 96 | .engine(engine) 97 | .operator(operator6) 98 | ; 99 | OperatorWrapper wrapper7 = new OperatorWrapper() 100 | .id("7") 101 | .engine(engine) 102 | .operator(operator7) 103 | .depend("6") 104 | ; 105 | 106 | return new OperatorWrapperGroup(engine) 107 | .beginWrapperIds("6") 108 | .endWrapperIds("7") 109 | .children("6", "7") 110 | .init() 111 | ; 112 | } 113 | 114 | private OperatorWrapperGroup buildGroup3(DagEngine engine, OperatorWrapperGroup group1, OperatorWrapperGroup group2) { 115 | group1.next("8"); 116 | group2.next("8"); 117 | 118 | OperatorWrapper wrapper8 = new OperatorWrapper() 119 | .id("8") 120 | .engine(engine) 121 | .operator(operator8) 122 | ; 123 | 124 | return new OperatorWrapperGroup(engine) 125 | .beginWrapperIds(group1.getGroupBeginId(), group2.getGroupBeginId()) 126 | .endWrapperIds("8") 127 | .children(group1.getId(), group2.getId(), "8") 128 | .init() 129 | ; 130 | } 131 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/nest/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group.nest; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator1 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("1..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/nest/Operator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group.nest; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator2 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("2..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/nest/Operator3.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group.nest; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator3 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("3..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/nest/Operator4.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group.nest; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator4 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("4..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/nest/Operator5.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group.nest; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator5 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | //业务逻辑部分 15 | TimeUnit.MILLISECONDS.sleep(1000); 16 | System.out.println("5..."); 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/nest/Operator6.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group.nest; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator6 implements IOperator { 10 | @Override 11 | public Integer execute(Integer param) throws Exception { 12 | //业务逻辑部分 13 | System.out.println("6..."); 14 | return null; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/nest/Operator7.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group.nest; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator7 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | //业务逻辑部分 15 | TimeUnit.MILLISECONDS.sleep(1000); 16 | System.out.println("7..."); 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/nest/Operator8.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group.nest; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator8 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | //业务逻辑部分 15 | TimeUnit.MILLISECONDS.sleep(1000); 16 | System.out.println("8..."); 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/group/nest/Operator9.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.group.nest; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator9 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | //业务逻辑部分 15 | TimeUnit.MILLISECONDS.sleep(1000); 16 | System.out.println("9..."); 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/listener/ListenerTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.listener; 2 | 3 | import org.taskflow.core.DagEngine; 4 | import org.taskflow.core.event.OperatorEventEnum; 5 | import org.taskflow.core.listener.OperatorListener; 6 | import org.taskflow.core.thread.pool.CustomThreadPool; 7 | import org.taskflow.core.wrapper.OperatorWrapper; 8 | import org.junit.Test; 9 | 10 | import java.util.concurrent.ExecutorService; 11 | 12 | /** 13 | * 节点执行状态监听器 14 | * Created by ytyht226 on 2022/3/17. 15 | */ 16 | public class ListenerTest { 17 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 18 | Operator1 operator1 = new Operator1(); 19 | Operator2 operator2 = new Operator2(); 20 | Operator3 operator3 = new Operator3(); 21 | 22 | @Test 23 | public void test() { 24 | OperatorListener listener1 = getListener(); 25 | DagEngine engine = new DagEngine(executor); 26 | OperatorWrapper wrapper1 = new OperatorWrapper() 27 | .id("1") 28 | .engine(engine) 29 | .operator(operator1) 30 | //给节点1添加三种执行状态的监听器,开始、异常、正常结束 31 | .addListener(listener1, OperatorEventEnum.START) 32 | .addListener(listener1, OperatorEventEnum.ERROR) 33 | .addListener(listener1, OperatorEventEnum.SUCCESS) 34 | ; 35 | OperatorWrapper wrapper2 = new OperatorWrapper() 36 | .id("2") 37 | .engine(engine) 38 | .operator(operator2) 39 | .addParamFromWrapperId("1") 40 | ; 41 | OperatorWrapper wrapper3 = new OperatorWrapper() 42 | .id("3") 43 | .engine(engine) 44 | .operator(operator3) 45 | .addParamFromWrapperId("2") 46 | ; 47 | 48 | engine.runAndWait(900_000); 49 | if (engine.getEx() != null) { 50 | engine.getEx().printStackTrace(); 51 | } 52 | } 53 | 54 | /** 55 | * 不同的监听器状态对应的处理逻辑 56 | */ 57 | private OperatorListener getListener() { 58 | return (wrapper, eventEnum) -> { 59 | if (eventEnum == OperatorEventEnum.START) { 60 | System.out.println("Op1 start..."); 61 | } 62 | if (eventEnum == OperatorEventEnum.SUCCESS) { 63 | System.out.println("Op1 success..."); 64 | } 65 | if (eventEnum == OperatorEventEnum.ERROR) { 66 | System.out.println("Op1 error..."); 67 | } 68 | }; 69 | } 70 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/listener/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.listener; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/4/1. 10 | */ 11 | public class Operator1 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | param = 1; 15 | TimeUnit.MILLISECONDS.sleep(10); 16 | System.out.println("Operator1 execute..."); 17 | return param; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/listener/Operator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.listener; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/4/1. 10 | */ 11 | public class Operator2 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | TimeUnit.MILLISECONDS.sleep(10); 15 | return param * 2; 16 | } 17 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/listener/Operator3.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.listener; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/4/1. 10 | */ 11 | public class Operator3 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | TimeUnit.MILLISECONDS.sleep(100); 15 | return param * 3; 16 | } 17 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | import org.taskflow.config.op.OpConfig; 6 | 7 | /** 8 | * Created by ytyht226 on 2022/6/23. 9 | */ 10 | public class Operator1 implements IOperator { 11 | @Override 12 | public OpConfig execute(OpConfig param) throws Exception { 13 | //业务逻辑部分 14 | 15 | param.getExtMap().put("op1", "op1"); 16 | return param; 17 | } 18 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo/Operator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | import org.taskflow.config.op.OpConfig; 6 | 7 | /** 8 | * Created by ytyht226 on 2022/6/23. 9 | */ 10 | public class Operator2 implements IOperator { 11 | @Override 12 | public OpConfig execute(OpConfig param) throws Exception { 13 | //业务逻辑部分 14 | 15 | param.getExtMap().put("op2", "op2"); 16 | return param; 17 | } 18 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo/Operator3.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | import org.taskflow.config.op.OpConfig; 6 | 7 | /** 8 | * Created by ytyht226 on 2022/6/23. 9 | */ 10 | public class Operator3 implements IOperator { 11 | @Override 12 | public OpConfig execute(OpConfig param) throws Exception { 13 | //业务逻辑部分 14 | 15 | param.getExtMap().put("op3", "op3"); 16 | return param; 17 | } 18 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo/ParamTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo; 2 | 3 | import org.junit.Test; 4 | import org.taskflow.common.util.gson.GsonUtil; 5 | import org.taskflow.config.op.OpConfig; 6 | import org.taskflow.core.DagEngine; 7 | import org.taskflow.core.thread.pool.CustomThreadPool; 8 | import org.taskflow.core.wrapper.OperatorWrapper; 9 | import org.taskflow.example.param.entity.OpConfigEntity; 10 | 11 | import java.util.concurrent.ExecutorService; 12 | 13 | /** 14 | * 节点参数来源 15 | * 不设置op参数,默认使用请求上下文 16 | * 执行顺序:1 -> 2 -> 3 17 | * Created by ytyht226 on 2022/6/23. 18 | */ 19 | @SuppressWarnings("all") 20 | public class ParamTest { 21 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 22 | Operator1 operator1 = new Operator1(); 23 | Operator2 operator2 = new Operator2(); 24 | Operator3 operator3 = new Operator3(); 25 | 26 | @Test 27 | public void test() { 28 | //请求上下文 29 | OpConfig opConfig = OpConfigEntity.getOpConfig(); 30 | System.out.println("before: " + GsonUtil.prettyPrint(opConfig)); 31 | DagEngine engine = new DagEngine(opConfig, executor); 32 | OperatorWrapper wrapper1 = new OperatorWrapper() 33 | .id("1") 34 | .engine(engine) 35 | .operator(operator1) 36 | .next("2") 37 | ; 38 | OperatorWrapper wrapper2 = new OperatorWrapper() 39 | .id("2") 40 | .engine(engine) 41 | .operator(operator2) 42 | .next("3") 43 | ; 44 | OperatorWrapper wrapper3 = new OperatorWrapper() 45 | .id("3") 46 | .engine(engine) 47 | .operator(operator3) 48 | ; 49 | 50 | engine.runAndWait(300_000); 51 | System.out.println("after: " + GsonUtil.prettyPrint(opConfig)); 52 | if (engine.getEx() != null) { 53 | engine.getEx().printStackTrace(); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo1/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo1; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | import org.taskflow.config.op.OpConfig; 6 | 7 | /** 8 | * Created by ytyht226 on 2022/6/23. 9 | */ 10 | public class Operator1 implements IOperator { 11 | @Override 12 | public String execute(OpConfig param) throws Exception { 13 | //业务逻辑部分 14 | String proxyObjName = param.getOpParamConfig().getProxyObjName(); 15 | System.out.println("1: " + proxyObjName); 16 | return proxyObjName; 17 | } 18 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo1/Operator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo1; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | /** 7 | * Created by ytyht226 on 2022/6/23. 8 | */ 9 | public class Operator2 implements IOperator { 10 | @Override 11 | public Object execute(String param) throws Exception { 12 | //业务逻辑部分 13 | 14 | Object obj = Class.forName(param).getDeclaredConstructor().newInstance(); 15 | System.out.println("2: " + obj); 16 | return obj; 17 | } 18 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo1/Operator3.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo1; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | import org.taskflow.config.op.OpConfig; 6 | import org.taskflow.config.op.param.OpParamConfig; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator3 implements IOperator { 12 | @Override 13 | public OpConfig execute(Object param) throws Exception { 14 | //业务逻辑部分 15 | OpConfig opConfig = (OpConfig) param; 16 | OpParamConfig opParamConfig = new OpParamConfig(); 17 | opParamConfig.setProxyObjName("Operator3"); 18 | opConfig.setOpParamConfig(opParamConfig); 19 | return opConfig; 20 | } 21 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo1/ParamTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo1; 2 | 3 | import org.junit.Test; 4 | import org.taskflow.config.op.OpConfig; 5 | import org.taskflow.core.DagEngine; 6 | import org.taskflow.core.thread.pool.CustomThreadPool; 7 | import org.taskflow.core.wrapper.OperatorWrapper; 8 | import org.taskflow.example.param.entity.OpConfigEntity; 9 | 10 | import java.util.concurrent.ExecutorService; 11 | 12 | /** 13 | * 节点参数来源 14 | * 开始节点使用上下文,其它节点入参使用依赖op的返回结果 15 | * 执行顺序:1 -> 2 -> 3 16 | * Created by ytyht226 on 2022/6/23. 17 | */ 18 | @SuppressWarnings("all") 19 | public class ParamTest { 20 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 21 | Operator1 operator1 = new Operator1(); 22 | Operator2 operator2 = new Operator2(); 23 | Operator3 operator3 = new Operator3(); 24 | 25 | @Test 26 | public void test() { 27 | //请求上下文 28 | OpConfig opConfig = OpConfigEntity.getOpConfig(); 29 | DagEngine engine = new DagEngine(executor); 30 | OperatorWrapper wrapper1 = new OperatorWrapper() 31 | .id("1") 32 | .engine(engine) 33 | .operator(operator1) 34 | .next("2") 35 | .context(opConfig) //参数来源是外部变量(请求上下文) 36 | ; 37 | OperatorWrapper wrapper2 = new OperatorWrapper() 38 | .id("2") 39 | .engine(engine) 40 | .operator(operator2) 41 | .next("3") 42 | .addParamFromWrapperId("1") //参数来源是其它节点的结果 43 | ; 44 | OperatorWrapper wrapper3 = new OperatorWrapper() 45 | .id("3") 46 | .engine(engine) 47 | .operator(operator3) 48 | .addParamFromWrapperId("2") //参数来源是其它节点的结果 49 | ; 50 | 51 | engine.runAndWait(300_000); 52 | System.out.println(wrapper3.getOperatorResult().getResult()); 53 | if (engine.getEx() != null) { 54 | engine.getEx().printStackTrace(); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo2/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo2; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | import org.taskflow.config.op.OpConfig; 6 | 7 | /** 8 | * Created by ytyht226 on 2022/6/23. 9 | */ 10 | public class Operator1 implements IOperator { 11 | @Override 12 | public String execute(OpConfig param) throws Exception { 13 | //业务逻辑部分 14 | String proxyObjName = param.getOpParamConfig().getProxyObjName(); 15 | System.out.println("1: " + proxyObjName); 16 | return proxyObjName; 17 | } 18 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo2/Operator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo2; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | import org.taskflow.config.op.OpConfig; 6 | import org.taskflow.config.op.param.OpParamConfig; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator2 implements IOperator { 12 | @Override 13 | public OpConfig execute(String param) throws Exception { 14 | //业务逻辑部分 15 | 16 | Object obj = Class.forName(param).getDeclaredConstructor().newInstance(); 17 | OpConfig opConfig = (OpConfig) obj; 18 | OpParamConfig opParamConfig = new OpParamConfig(); 19 | opParamConfig.setProxyObjName("Operator2"); 20 | opConfig.setOpParamConfig(opParamConfig); 21 | System.out.println("2: " + opConfig); 22 | return opConfig; 23 | } 24 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo2/Operator3.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo2; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | import org.taskflow.config.op.OpConfig; 6 | import org.taskflow.config.op.param.OpParamConfig; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator3 implements IOperator { 12 | @Override 13 | public OpConfig execute(String param) throws Exception { 14 | //业务逻辑部分 15 | 16 | Object obj = Class.forName(param).getDeclaredConstructor().newInstance(); 17 | OpConfig opConfig = (OpConfig) obj; 18 | OpParamConfig opParamConfig = new OpParamConfig(); 19 | opParamConfig.setProxyObjName("Operator3"); 20 | opConfig.setOpParamConfig(opParamConfig); 21 | System.out.println("3: " + opConfig); 22 | return opConfig; 23 | } 24 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo2/Operator4.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo2; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | import org.taskflow.config.op.OpConfig; 6 | import org.taskflow.config.op.param.OpParamConfig; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Created by ytyht226 on 2022/6/23. 12 | */ 13 | public class Operator4 implements IOperator, List> { 14 | @Override 15 | public List execute(List param) throws Exception { 16 | for (OpConfig opConfig : param) { 17 | OpParamConfig opParamConfig = opConfig.getOpParamConfig(); 18 | if (opParamConfig.getProxyObjName().equals("Operator2")) { 19 | opParamConfig.setMethodName("Operator2_method"); 20 | } else if (opParamConfig.getProxyObjName().equals("Operator3")) { 21 | opParamConfig.setMethodName("Operator3_method"); 22 | } 23 | } 24 | return param; 25 | } 26 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo2/ParamTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo2; 2 | 3 | import org.junit.Test; 4 | import org.taskflow.config.op.OpConfig; 5 | import org.taskflow.core.DagEngine; 6 | import org.taskflow.core.thread.pool.CustomThreadPool; 7 | import org.taskflow.core.wrapper.OperatorWrapper; 8 | import org.taskflow.example.param.entity.OpConfigEntity; 9 | 10 | import java.util.List; 11 | import java.util.concurrent.ExecutorService; 12 | 13 | /** 14 | * 节点参数来源 15 | * 开始节点使用上下文,其它节点入参使用依赖op的返回结果(依赖多个) 16 | * 执行顺序:1 -> (2、3) -> 4 17 | * Created by ytyht226 on 2022/6/23. 18 | */ 19 | @SuppressWarnings("all") 20 | public class ParamTest { 21 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 22 | Operator1 operator1 = new Operator1(); 23 | Operator2 operator2 = new Operator2(); 24 | Operator3 operator3 = new Operator3(); 25 | Operator4 operator4 = new Operator4(); 26 | 27 | @Test 28 | public void test() { 29 | //请求上下文 30 | OpConfig opConfig = OpConfigEntity.getOpConfig(); 31 | DagEngine engine = new DagEngine(executor); 32 | OperatorWrapper wrapper1 = new OperatorWrapper() 33 | .id("1") 34 | .engine(engine) 35 | .operator(operator1) 36 | .next("2") 37 | .context(opConfig) //参数来源是外部变量(请求上下文) 38 | ; 39 | OperatorWrapper wrapper2 = new OperatorWrapper() 40 | .id("2") 41 | .engine(engine) 42 | .operator(operator2) 43 | .addParamFromWrapperId("1") //参数来源是其它节点的结果 44 | ; 45 | OperatorWrapper wrapper3 = new OperatorWrapper() 46 | .id("3") 47 | .engine(engine) 48 | .operator(operator3) 49 | .addParamFromWrapperId("1") //参数来源是其它节点的结果 50 | ; 51 | 52 | OperatorWrapper wrapper4 = new OperatorWrapper, List>() 53 | .id("4") 54 | .engine(engine) 55 | .operator(operator4) 56 | .addParamFromWrapperId("2", "3") //参数来源是其它节点的结果 57 | ; 58 | 59 | engine.runAndWait(300_000); 60 | if (engine.getEx() != null) { 61 | engine.getEx().printStackTrace(); 62 | } 63 | System.out.println(wrapper4.getOperatorResult().getResult()); 64 | } 65 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo3/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo3; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | import org.taskflow.config.op.OpConfig; 6 | 7 | /** 8 | * Created by ytyht226 on 2022/6/23. 9 | */ 10 | public class Operator1 implements IOperator { 11 | @Override 12 | public OpConfig execute(OpConfig context) throws Exception { 13 | //业务逻辑部分 14 | context.getOpParamConfig().setMethodName("Operator1.execute"); 15 | return context; 16 | } 17 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo3/Operator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo3; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | import org.taskflow.config.op.OpConfig; 6 | import org.taskflow.config.op.param.OpParamConfig; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator2 implements IOperator { 12 | @Override 13 | public OpParamConfig execute(OpConfig context) throws Exception { 14 | //业务逻辑部分 15 | 16 | OpParamConfig opParamConfig = context.getOpParamConfig(); 17 | return opParamConfig; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo3/Operator3.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo3; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | import org.taskflow.config.op.OpConfig; 6 | 7 | import java.util.Map; 8 | 9 | /** 10 | * Created by ytyht226 on 2022/6/23. 11 | */ 12 | public class Operator3 implements IOperator> { 13 | @Override 14 | public Map execute(OpConfig context) throws Exception { 15 | //业务逻辑部分 16 | Map extMap = context.getExtMap(); 17 | return extMap; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo3/ParamOperator4.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo3; 2 | 3 | import org.taskflow.config.op.param.JsonPathConfig; 4 | import org.taskflow.config.op.param.OpParamConfig; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | /** 10 | * Created by ytyht226 on 2022/11/22. 11 | */ 12 | public class ParamOperator4 { 13 | 14 | public Map apply(String proxyObjName, OpParamConfig opParamConfig, Map info, JsonPathConfig pathConfig) { 15 | Map map = new HashMap<>(); 16 | map.put("proxyObjName", proxyObjName); 17 | map.put("opParamConfig", opParamConfig); 18 | map.put("info", info); 19 | map.put("pathConfig", pathConfig); 20 | return map; 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo3/ParamTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo3; 2 | 3 | import org.junit.Test; 4 | import org.taskflow.common.util.gson.GsonUtil; 5 | import org.taskflow.config.op.OpConfig; 6 | import org.taskflow.config.op.param.OpParamConfig; 7 | import org.taskflow.core.DagEngine; 8 | import org.taskflow.core.thread.pool.CustomThreadPool; 9 | import org.taskflow.core.wrapper.OperatorWrapper; 10 | import org.taskflow.example.param.entity.OpConfigEntity; 11 | 12 | import java.util.Map; 13 | import java.util.concurrent.ExecutorService; 14 | 15 | /** 16 | * 节点参数来源 17 | * 使用json-path指定参数来源 18 | * 执行顺序:1 -> (2、3) -> 4 19 | * Created by ytyht226 on 2022/6/23. 20 | */ 21 | @SuppressWarnings("all") 22 | public class ParamTest { 23 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 24 | Operator1 operator1 = new Operator1(); 25 | Operator2 operator2 = new Operator2(); 26 | Operator3 operator3 = new Operator3(); 27 | ParamOperator4 operator4 = new ParamOperator4(); 28 | 29 | @Test 30 | public void test() { 31 | //请求上下文 32 | OpConfig opConfig = OpConfigEntity.getOpConfig(); 33 | 34 | System.out.println(GsonUtil.prettyPrint(opConfig)); 35 | System.out.println("=========================="); 36 | 37 | DagEngine engine = new DagEngine(opConfig, executor); 38 | OperatorWrapper wrapper1 = new OperatorWrapper() 39 | .id("1") 40 | .engine(engine) 41 | .operator(operator1) 42 | .next("2", "3") 43 | ; 44 | OperatorWrapper wrapper2 = new OperatorWrapper() 45 | .id("2") 46 | .engine(engine) 47 | .operator(operator2) 48 | .next("4") 49 | ; 50 | OperatorWrapper wrapper3 = new OperatorWrapper>() 51 | .id("3") 52 | .engine(engine) 53 | .operator(operator3) 54 | .next("4") 55 | ; 56 | 57 | //测试配置示例: 58 | /** 59 | { 60 | "opParamConfig":{ 61 | "methodName":"apply", 62 | "jsonPathList":[ 63 | { 64 | "path":"#.opParamConfig.proxyObjName", 65 | "type":"java.lang.String" 66 | }, 67 | { 68 | "path":"$2", 69 | "type":"org.taskflow.config.op.param.OpParamConfig" 70 | }, 71 | { 72 | "path":"$3.info", 73 | "type":"java.util.Map" 74 | }, 75 | { 76 | "type":"org.taskflow.config.op.param.JsonPathConfig", 77 | "value":{ 78 | "path":"xxx", 79 | "type":"java.lang.String" 80 | } 81 | } 82 | ] 83 | } 84 | } 85 | */ 86 | String op4Config = "{\n" + 87 | " \"opParamConfig\":{\n" + 88 | " \"methodName\":\"apply\",\n" + 89 | " \"jsonPathList\":[\n" + 90 | " {\n" + 91 | " \"path\":\"#.opParamConfig.proxyObjName\",\n" + 92 | " \"type\":\"java.lang.String\"\n" + 93 | " },\n" + 94 | " {\n" + 95 | " \"path\":\"$2\",\n" + 96 | " \"type\":\"org.taskflow.config.op.param.OpParamConfig\"\n" + 97 | " },\n" + 98 | " {\n" + 99 | " \"path\":\"$3.info\",\n" + 100 | " \"type\":\"java.util.Map\"\n" + 101 | " },\n" + 102 | " {\n" + 103 | " \"type\":\"org.taskflow.config.op.param.JsonPathConfig\",\n" + 104 | " \"value\":{\n" + 105 | " \"path\":\"xxx\",\n" + 106 | " \"type\":\"java.lang.String\"\n" + 107 | " }\n" + 108 | " }\n" + 109 | " ]\n" + 110 | " }\n" + 111 | "}"; 112 | 113 | OperatorWrapper wrapper4 = new OperatorWrapper>() 114 | .id("4") 115 | .engine(engine) 116 | /** 117 | * 设置节点4的相关配置,当前只有参数配置,即:opParamConfig 118 | * @see OpParamConfig 119 | */ 120 | .opConfig(op4Config) 121 | /** 122 | * 要执行的目标对象,目标方法通过节点配置指定,即 OpParamConfig 中的 methodName字段 123 | */ 124 | .proxyObj(operator4) 125 | ; 126 | 127 | engine.runAndWait(300_000); 128 | System.out.println(GsonUtil.prettyPrint(wrapper4.getOperatorResult().getResult())); 129 | if (engine.getEx() != null) { 130 | engine.getEx().printStackTrace(); 131 | } 132 | } 133 | 134 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo4/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo4; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | import org.taskflow.config.op.OpConfig; 6 | 7 | /** 8 | * Created by ytyht226 on 2022/6/23. 9 | */ 10 | public class Operator1 implements IOperator { 11 | @Override 12 | public OpConfig execute(OpConfig context) throws Exception { 13 | //业务逻辑部分 14 | context.getOpParamConfig().setMethodName("Operator1.execute"); 15 | return context; 16 | } 17 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo4/ParamOperator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo4; 2 | 3 | import org.taskflow.config.op.param.JsonPathConfig; 4 | import org.taskflow.config.op.param.OpParamConfig; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | /** 10 | * Created by ytyht226 on 2022/11/22. 11 | */ 12 | public class ParamOperator2 { 13 | 14 | public Map apply(String proxyObjName, OpParamConfig opParamConfig, JsonPathConfig jsonPathConfig, Map info) { 15 | Map map = new HashMap<>(); 16 | map.put("proxyObjName", proxyObjName); 17 | map.put("opParamConfig", opParamConfig); 18 | map.put("jsonPathConfig", jsonPathConfig); 19 | map.put("info", info); 20 | return map; 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/demo4/ParamTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.demo4; 2 | 3 | import org.junit.Test; 4 | import org.taskflow.common.util.gson.GsonUtil; 5 | import org.taskflow.config.op.OpConfig; 6 | import org.taskflow.core.DagEngine; 7 | import org.taskflow.core.operator.IParamParseOperator; 8 | import org.taskflow.core.operator.RecurseParamParseOperator; 9 | import org.taskflow.core.thread.pool.CustomThreadPool; 10 | import org.taskflow.core.wrapper.OperatorWrapper; 11 | import org.taskflow.example.param.entity.OpConfigEntity; 12 | 13 | import java.util.Map; 14 | import java.util.concurrent.ExecutorService; 15 | 16 | /** 17 | * 节点参数来源 18 | * 使用json-path指定参数来源 19 | * 执行顺序:1 -> (2、3) -> 4 -> 5 20 | * Created by ytyht226 on 2022/6/23. 21 | */ 22 | @SuppressWarnings("all") 23 | public class ParamTest { 24 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 25 | Operator1 operator1 = new Operator1(); 26 | ParamOperator2 paramOperator2 = new ParamOperator2(); 27 | IParamParseOperator paramParseOperator = new RecurseParamParseOperator(); 28 | 29 | @Test 30 | public void test() { 31 | //请求上下文 32 | OpConfig opConfig = OpConfigEntity.getOpConfig(); 33 | 34 | System.out.println(GsonUtil.prettyPrint(opConfig)); 35 | System.out.println("=========================="); 36 | 37 | DagEngine engine = new DagEngine(opConfig, executor); 38 | OperatorWrapper wrapper1 = new OperatorWrapper() 39 | .id("1") 40 | .engine(engine) 41 | .operator(operator1) 42 | .next("2") 43 | ; 44 | 45 | //测试配置示例: 46 | /** 47 | { 48 | "opParamConfig":{ 49 | "methodName":"apply", 50 | "jsonPathList":[ 51 | { 52 | "path":"#.opParamConfig.proxyObjName", 53 | "type":"java.lang.String" 54 | }, 55 | { 56 | "path":"$2.opParamConfig", 57 | "type":"org.taskflow.config.op.param.OpParamConfig", 58 | "value":{ 59 | "proxyObjName":"xxx", 60 | "jsonPathList":"$1.opParamConfig.jsonPathList[:1]" 61 | } 62 | }, 63 | { 64 | "type":"org.taskflow.config.op.param.JsonPathConfig", 65 | "value":{ 66 | "path":"$1.opParamConfig.proxyObjName", 67 | "type":"java.lang.String" 68 | } 69 | }, 70 | { 71 | "type":"java.util.Map", 72 | "value":{ 73 | "address":"$1.extMap.info.address", 74 | "age":"$1.extMap.info.age", 75 | "proxyObjName":"$1.opParamConfig.proxyObjName", 76 | "methodName":"test" 77 | } 78 | } 79 | ] 80 | } 81 | } 82 | */ 83 | String op2Config = "{\n" + 84 | " \"opParamConfig\":{\n" + 85 | " \"methodName\":\"apply\",\n" + 86 | " \"jsonPathList\":[\n" + 87 | " {\n" + 88 | " \"path\":\"#.opParamConfig.proxyObjName\",\n" + 89 | " \"type\":\"java.lang.String\"\n" + 90 | " },\n" + 91 | " {\n" + 92 | " \"path\":\"$2.opParamConfig\",\n" + 93 | " \"type\":\"org.taskflow.config.op.param.OpParamConfig\",\n" + 94 | " \"value\":{\n" + 95 | " \"proxyObjName\":\"xxx\",\n" + 96 | " \"jsonPathList\":\"$1.opParamConfig.jsonPathList[:1]\"\n" + 97 | " }\n" + 98 | " },\n" + 99 | " {\n" + 100 | " \"type\":\"org.taskflow.config.op.param.JsonPathConfig\",\n" + 101 | " \"value\":{\n" + 102 | " \"path\":\"$1.opParamConfig.proxyObjName\",\n" + 103 | " \"type\":\"java.lang.String\"\n" + 104 | " }\n" + 105 | " },\n" + 106 | " {\n" + 107 | " \"type\":\"java.util.Map\",\n" + 108 | " \"value\":{\n" + 109 | " \"address\":\"$1.extMap.info.address\",\n" + 110 | " \"age\":\"$1.extMap.info.age\",\n" + 111 | " \"proxyObjName\":\"$1.opParamConfig.proxyObjName\",\n" + 112 | " \"methodName\":\"test\"\n" + 113 | " }\n" + 114 | " }\n" + 115 | " ]\n" + 116 | " }\n" + 117 | "}"; 118 | 119 | OperatorWrapper wrapper2 = new OperatorWrapper>() 120 | .id("2") 121 | .engine(engine) 122 | .opConfig(op2Config, paramParseOperator) 123 | .proxyObj(paramOperator2) 124 | ; 125 | 126 | engine.runAndWait(300_000); 127 | System.out.println(GsonUtil.prettyPrint(wrapper2.getOperatorResult().getResult())); 128 | if (engine.getEx() != null) { 129 | engine.getEx().printStackTrace(); 130 | } 131 | } 132 | 133 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/param/entity/OpConfigEntity.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.param.entity; 2 | 3 | import org.taskflow.config.op.OpConfig; 4 | import org.taskflow.config.op.param.JsonPathConfig; 5 | import org.taskflow.config.op.param.OpParamConfig; 6 | 7 | import java.util.ArrayList; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | /** 13 | * 测试使用的实体 14 | * Created by ytyht226 on 2022/11/23. 15 | */ 16 | public class OpConfigEntity { 17 | 18 | /** 19 | 20 | { 21 | "opParamConfig": { 22 | "proxyObjName": "org.taskflow.config.op.OpConfig", 23 | "methodName": "test", 24 | "jsonPathList": [ 25 | { 26 | "path": "#.request.param", 27 | "type": "java.lang.String", 28 | "typeClass": null, 29 | "defaultValue": "test" 30 | }, 31 | { 32 | "path": "$1.response.param", 33 | "type": "java.lang.Integer", 34 | "typeClass": null, 35 | "defaultValue": null 36 | } 37 | ] 38 | }, 39 | "extMap": { 40 | "score": 100.05, 41 | "code": 100, 42 | "city": "bj", 43 | "info": { 44 | "address": "hd", 45 | "age": 18 46 | } 47 | } 48 | } 49 | 50 | */ 51 | public static OpConfig getOpConfig() { 52 | OpConfig opConfig = new OpConfig(); 53 | 54 | opConfig.setOpParamConfig(getOpParamConfig()); 55 | Map extMap = new HashMap<>(); 56 | extMap.put("city", "bj"); 57 | extMap.put("code", 100); 58 | extMap.put("score", 100.05); 59 | 60 | Map infoMap = new HashMap<>(); 61 | infoMap.put("address", "hd"); 62 | infoMap.put("age", 18); 63 | extMap.put("info", infoMap); 64 | 65 | opConfig.setExtMap(extMap); 66 | 67 | return opConfig; 68 | } 69 | 70 | private static OpParamConfig getOpParamConfig() { 71 | OpParamConfig opParamConfig = new OpParamConfig(); 72 | opParamConfig.setProxyObjName("org.taskflow.config.op.OpConfig"); 73 | opParamConfig.setMethodName("test"); 74 | opParamConfig.setJsonPathList(getJsonPathConfigList()); 75 | return opParamConfig; 76 | } 77 | 78 | private static List getJsonPathConfigList() { 79 | List jsonPathConfigList = new ArrayList<>(); 80 | 81 | JsonPathConfig config1 = new JsonPathConfig(); 82 | config1.setPath("#.request.param"); 83 | config1.setType("java.lang.String"); 84 | config1.setValue("test"); 85 | 86 | JsonPathConfig config2 = new JsonPathConfig(); 87 | config2.setPath("$1.response.param"); 88 | config2.setType("java.lang.Integer"); 89 | 90 | jsonPathConfigList.add(config1); 91 | jsonPathConfigList.add(config2); 92 | 93 | return jsonPathConfigList; 94 | } 95 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/simpledemo/DemoTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.simpledemo; 2 | 3 | import org.taskflow.core.DagEngine; 4 | import org.taskflow.core.thread.pool.CustomThreadPool; 5 | import org.taskflow.core.wrapper.OperatorWrapper; 6 | import org.junit.Test; 7 | 8 | import java.util.concurrent.ExecutorService; 9 | 10 | /** 11 | * 流程编排示例 12 | * Created by ytyht226 on 2022/6/23. 13 | */ 14 | public class DemoTest { 15 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 16 | Operator1 operator1 = new Operator1(); 17 | Operator2 operator2 = new Operator2(); 18 | Operator3 operator3 = new Operator3(); 19 | 20 | @Test 21 | public void test() { 22 | // 执行流程:1 ->2 ->3 23 | DagEngine engine = new DagEngine(executor); 24 | OperatorWrapper wrapper1 = new OperatorWrapper() 25 | .id("1") 26 | .engine(engine) 27 | .operator(operator1) 28 | .next("2") 29 | ; 30 | OperatorWrapper wrapper2 = new OperatorWrapper() 31 | .id("2") 32 | .engine(engine) 33 | .operator(operator2) 34 | ; 35 | OperatorWrapper wrapper3 = new OperatorWrapper() 36 | .id("3") 37 | .engine(engine) 38 | .operator(operator3) 39 | .depend("2") 40 | ; 41 | engine.runAndWait(500_000); 42 | if (engine.getEx() != null) { 43 | engine.getEx().printStackTrace(); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/simpledemo/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.simpledemo; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator1 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | //业务逻辑部分 15 | TimeUnit.SECONDS.sleep(1); 16 | System.out.println("Operator1..."); 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/simpledemo/Operator2.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.simpledemo; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator2 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | //业务逻辑部分 15 | TimeUnit.SECONDS.sleep(1); 16 | System.out.println("Operator2..."); 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/simpledemo/Operator3.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.simpledemo; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator3 implements IOperator { 12 | @Override 13 | public Integer execute(Integer param) throws Exception { 14 | //业务逻辑部分 15 | TimeUnit.SECONDS.sleep(1); 16 | System.out.println("Operator3..."); 17 | return null; 18 | } 19 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/task/BatchIntegerOperator.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.task; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | import org.taskflow.core.task.MultiParamTaskResult; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.concurrent.TimeUnit; 10 | 11 | /** 12 | * Created by ytyht226 on 2023/3/16. 13 | */ 14 | public class BatchIntegerOperator implements IOperator, List>> { 15 | @Override 16 | public List> execute(List param) throws Exception { 17 | TimeUnit.SECONDS.sleep(1); 18 | List> taskResults = new ArrayList<>(); 19 | for (int id : param) { 20 | Model model = new Model(id, "name_" + id); 21 | MultiParamTaskResult result = new MultiParamTaskResult<>(id, model); 22 | taskResults.add(result); 23 | } 24 | return taskResults; 25 | } 26 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/task/BatchModelOperator.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.task; 2 | 3 | import org.taskflow.core.operator.IOperator; 4 | import org.taskflow.core.task.MultiParamTaskResult; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * Created by ytyht226 on 2023/3/16. 11 | */ 12 | public class BatchModelOperator implements IOperator, List>> { 13 | @Override 14 | public List> execute(List param) throws Exception { 15 | // int a = 5 / 0; 16 | List> taskResults = new ArrayList<>(); 17 | for (Model model : param) { 18 | model.setName("name_" + model.getId()); 19 | ModelResult modelResult = new ModelResult(); 20 | modelResult.setCode(200); 21 | modelResult.setMsg("SUCC"); 22 | modelResult.setModel(model); 23 | 24 | MultiParamTaskResult taskResult = new MultiParamTaskResult<>(model, modelResult); 25 | taskResults.add(taskResult); 26 | } 27 | return taskResults; 28 | } 29 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/task/IntegerOperator.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.task; 2 | 3 | import org.taskflow.core.operator.IOperator; 4 | 5 | import java.util.concurrent.TimeUnit; 6 | 7 | /** 8 | * Created by ytyht226 on 2023/3/16. 9 | */ 10 | public class IntegerOperator implements IOperator { 11 | @Override 12 | public Integer execute(Integer param) throws Exception { 13 | TimeUnit.SECONDS.sleep(1); 14 | return 10 * param; 15 | } 16 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/task/Model.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.task; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * Created by ytyht226 on 2023/3/17. 7 | */ 8 | @Data 9 | public class Model { 10 | private int id; 11 | private String name; 12 | 13 | public Model(int id) { 14 | this.id = id; 15 | } 16 | public Model(int id, String name) { 17 | this.id = id; 18 | this.name = name; 19 | } 20 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/task/ModelOperator.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.task; 2 | 3 | import org.taskflow.core.operator.IOperator; 4 | 5 | /** 6 | * Created by ytyht226 on 2023/3/16. 7 | */ 8 | public class ModelOperator implements IOperator { 9 | @Override 10 | public ModelResult execute(Model param) throws Exception { 11 | 12 | ModelResult modelResult = new ModelResult(); 13 | modelResult.setCode(200); 14 | modelResult.setMsg("SUCC"); 15 | modelResult.setModel(param); 16 | return modelResult; 17 | } 18 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/task/ModelResult.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.task; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * Created by ytyht226 on 2023/3/17. 7 | */ 8 | @Data 9 | public class ModelResult { 10 | private int code; 11 | private String msg; 12 | 13 | private Model model; 14 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/task/TaskTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.task; 2 | 3 | import org.taskflow.core.task.MultiParamTaskResult; 4 | import org.taskflow.core.task.TaskResult; 5 | import org.taskflow.core.task.TaskUtil; 6 | import org.taskflow.core.thread.pool.CustomThreadPool; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.concurrent.ExecutorService; 13 | 14 | /** 15 | * Created by ytyht226 on 2023/3/15. 16 | */ 17 | public class TaskTest { 18 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(50); 19 | IntegerOperator integerOperator = new IntegerOperator(); 20 | ModelOperator modelOperator = new ModelOperator(); 21 | BatchIntegerOperator batchIntegerOperator = new BatchIntegerOperator(); 22 | BatchModelOperator batchModelOperator = new BatchModelOperator(); 23 | 24 | //任务列表 25 | List idList = new ArrayList<>(); 26 | List modelList = new ArrayList<>(); 27 | 28 | @Before 29 | public void setUp() { 30 | for (int i = 1; i <= 100; i++) { 31 | idList.add(i); 32 | 33 | Model model = new Model(i); 34 | modelList.add(model); 35 | } 36 | } 37 | 38 | /** 39 | * 一个批次执行,task任务入参、出参都是简单的基本数据类型 40 | */ 41 | @Test 42 | public void parallelTaskTest1() { 43 | long begin = System.currentTimeMillis(); 44 | List> results = TaskUtil.parallelTask(idList, integerOperator, executor, 300_000); 45 | long end = System.currentTimeMillis(); 46 | System.out.println("cost: " + (end - begin)); 47 | for (TaskResult result : results) { 48 | System.out.println(result); 49 | } 50 | } 51 | 52 | /** 53 | * 一个批次执行,task任务入参、出参是自定义类型 54 | */ 55 | @Test 56 | public void parallelTaskTest2() { 57 | long begin = System.currentTimeMillis(); 58 | List> results = TaskUtil.parallelTask(modelList, modelOperator, executor, 300_000); 59 | long end = System.currentTimeMillis(); 60 | System.out.println("cost: " + (end - begin)); 61 | for (TaskResult result : results) { 62 | System.out.println(result); 63 | } 64 | } 65 | 66 | @Test 67 | public void serialTaskTest1() { 68 | long begin = System.currentTimeMillis(); 69 | List> results = TaskUtil.serialTask(idList, integerOperator, executor, 300_000); 70 | long end = System.currentTimeMillis(); 71 | System.out.println("cost: " + (end - begin)); 72 | for (TaskResult result : results) { 73 | System.out.println(result); 74 | } 75 | } 76 | 77 | /** 78 | * 将一组任务分多个批次执行,task任务入参、出参都是简单的基本数据类型 79 | */ 80 | @Test 81 | public void batchTaskTest1() { 82 | long begin = System.currentTimeMillis(); 83 | List> results = TaskUtil.serialBatchTask(idList, 2, integerOperator, executor, 300_000); 84 | long end = System.currentTimeMillis(); 85 | System.out.println("cost: " + (end - begin)); 86 | for (TaskResult result : results) { 87 | System.out.println(result); 88 | } 89 | } 90 | 91 | /** 92 | * 将一组任务分多个批次执行,task任务入参、出参是自定义类型 93 | */ 94 | @Test 95 | public void batchTaskTest2() { 96 | long begin = System.currentTimeMillis(); 97 | List> results = TaskUtil.serialBatchTask(modelList, 2, modelOperator, executor, 300_000); 98 | long end = System.currentTimeMillis(); 99 | System.out.println("cost: " + (end - begin)); 100 | for (TaskResult result : results) { 101 | System.out.println(result); 102 | } 103 | } 104 | 105 | /** 106 | * 将一批任务分批次执行(每个批次是一个任务,每个任务可以传入多个参数;比如调用的批量接口) 107 | * 批次之间串行 108 | */ 109 | @Test 110 | public void serialBatchMultiParamTask1() { 111 | long begin = System.currentTimeMillis(); 112 | List> results = TaskUtil.serialBatchMultiParamTask(idList, 2, batchIntegerOperator, executor, 300_000); 113 | long end = System.currentTimeMillis(); 114 | System.out.println("cost: " + (end - begin)); 115 | for (MultiParamTaskResult result : results) { 116 | System.out.println(result); 117 | } 118 | } 119 | 120 | /** 121 | * 将一批任务分批次执行(每个批次是一个任务,每个任务可以传入多个参数;比如调用的批量接口) 122 | * 批次之间串行,task任务入参、出参是自定义类型 123 | */ 124 | @Test 125 | public void serialBatchMultiParamTask2() { 126 | long begin = System.currentTimeMillis(); 127 | List> results = TaskUtil.serialBatchMultiParamTask(modelList, 50, batchModelOperator, executor, 300_000); 128 | long end = System.currentTimeMillis(); 129 | System.out.println("cost: " + (end - begin)); 130 | for (MultiParamTaskResult result : results) { 131 | System.out.println(result); 132 | } 133 | } 134 | 135 | /** 136 | * 将一批任务分批次执行(每个批次是一个任务,每个任务可以传入多个参数;比如调用的批量接口) 137 | * 批次之间并行 138 | */ 139 | @Test 140 | public void parallelBatchMultiParamTask1() { 141 | long begin = System.currentTimeMillis(); 142 | List> results = TaskUtil.parallelBatchMultiParamTask(idList, 2, batchIntegerOperator, executor, 300_000); 143 | long end = System.currentTimeMillis(); 144 | System.out.println("cost: " + (end - begin)); 145 | for (MultiParamTaskResult result : results) { 146 | System.out.println(result); 147 | } 148 | } 149 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/threadmodel/BlockTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.threadmodel; 2 | 3 | import org.taskflow.core.DagEngine; 4 | import org.taskflow.core.thread.pool.CustomThreadPool; 5 | import org.taskflow.core.wrapper.OperatorWrapper; 6 | import org.junit.Test; 7 | 8 | import java.util.concurrent.ExecutorService; 9 | 10 | /** 11 | * 线程模型--阻塞模式 12 | * Created by ytyht226 on 2022/6/23. 13 | */ 14 | public class BlockTest { 15 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 16 | Operator1 operator1 = new Operator1(); 17 | 18 | @Test 19 | public void test() { 20 | DagEngine engine = new DagEngine(executor); 21 | OperatorWrapper wrapper1 = new OperatorWrapper() 22 | .id("1") 23 | .engine(engine) 24 | .operator(operator1) 25 | ; 26 | 27 | engine.runAndWait(900_000); 28 | if (engine.getEx() != null) { 29 | engine.getEx().printStackTrace(); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/threadmodel/NonBlockTest.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.threadmodel; 2 | 3 | import org.taskflow.core.DagEngine; 4 | import org.taskflow.core.thread.pool.CustomThreadPool; 5 | import org.taskflow.core.wrapper.OperatorWrapper; 6 | import org.junit.Test; 7 | 8 | import java.util.concurrent.ExecutorService; 9 | 10 | /** 11 | * 线程模型--非阻塞模式 12 | * Created by ytyht226 on 2022/6/23. 13 | */ 14 | public class NonBlockTest { 15 | ExecutorService executor = CustomThreadPool.newFixedThreadPoolWrapper(5); 16 | private final Operator1 operator1 = new Operator1(); 17 | 18 | @Test 19 | public void test() { 20 | DagEngine engine = new DagEngine(executor); 21 | OperatorWrapper wrapper1 = new OperatorWrapper() 22 | .id("1") 23 | .engine(engine) 24 | .operator(operator1) 25 | ; 26 | 27 | engine.runWithCallback(900_000, this::engineCallback); 28 | 29 | System.out.println("main end..."); 30 | 31 | synchronized (operator1) { 32 | try { 33 | operator1.wait(); 34 | } catch (InterruptedException e) { 35 | e.printStackTrace(); 36 | } 37 | } 38 | } 39 | 40 | private void engineCallback() { 41 | System.out.println("engine callback..."); 42 | synchronized (operator1) { 43 | operator1.notify(); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /taskflow-example/src/main/java/org/taskflow/example/threadmodel/Operator1.java: -------------------------------------------------------------------------------- 1 | package org.taskflow.example.threadmodel; 2 | 3 | 4 | import org.taskflow.core.operator.IOperator; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | /** 9 | * Created by ytyht226 on 2022/6/23. 10 | */ 11 | public class Operator1 implements IOperator { 12 | 13 | @Override 14 | public Integer execute(Void param) throws Exception { 15 | TimeUnit.SECONDS.sleep(3); 16 | System.out.println("1..."); 17 | return 1; 18 | } 19 | } --------------------------------------------------------------------------------