You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dolphinscheduler.apache.org by we...@apache.org on 2024/04/07 02:03:55 UTC
(dolphinscheduler) 01/04: Add dolphinscheduler-workflow-engine module
This is an automated email from the ASF dual-hosted git repository.
wenjun pushed a commit to branch dev_wenjun_refactorMaster
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler.git
commit 5dcb0fb59c5392138616ddaffec5e2cecab3e35f
Author: Wenjun Ruan <we...@apache.org>
AuthorDate: Tue Mar 5 15:48:00 2024 +0800
Add dolphinscheduler-workflow-engine module
---
.../dao/entity/ProcessInstance.java | 8 +-
.../dao/repository/ProcessTaskRelationLogDao.java | 3 +
.../impl/ProcessTaskRelationLogDaoImpl.java | 6 +
.../server/master/dag/BasicDAG.java | 71 ++++++
.../dolphinscheduler/server/master/dag/DAG.java | 146 +++++++++++
.../server/master/dag/DAGEdge.java | 51 ++++
.../server/master/dag/DAGEngine.java | 148 +++++++++++
.../DAGEngineFactory.java} | 16 +-
.../server/master/dag/DAGNode.java | 92 +++++++
.../server/master/dag/IDAGEngine.java | 70 +++++
.../IDAGEngineFactory.java} | 8 +-
.../IDAGNodeAction.java} | 19 +-
.../IEventRepositoryFactory.java} | 10 +-
.../IEventfulExecutionRunnable.java} | 16 +-
.../ITaskExecutionContext.java} | 10 +-
.../ITaskExecutionContextFactory.java} | 8 +-
.../server/master/dag/ITaskExecutionRunnable.java | 59 +++++
.../ITaskExecutionRunnableFactory.java} | 8 +-
.../ITaskExecutionRunnableRepository.java} | 17 +-
.../ITaskExecutionRunnableRepositoryFactory.java} | 8 +-
.../IWorkflowDAG.java} | 11 +-
.../IWorkflowDAGFactory.java} | 19 +-
.../server/master/dag/IWorkflowEngine.java | 57 +++++
.../master/dag/IWorkflowExecutionContext.java | 35 ++-
.../server/master/dag/IWorkflowExecutionDAG.java | 74 ++++++
.../IWorkflowExecutionDAGFactory.java} | 9 +-
.../master/dag/IWorkflowExecutionRunnable.java | 39 ++-
.../MemoryEventRepositoryFactory.java} | 19 +-
.../TaskExecutionContext.java} | 19 +-
.../TaskExecutionRunnable.java} | 38 ++-
.../dag/TaskExecutionRunnableRepository.java | 68 +++++
.../TaskExecutionRunnableRepositoryFactory.java} | 14 +-
.../TaskExecutionValve.java} | 11 +-
.../TaskIdentify.java} | 8 +-
.../WorkflowDAG.java} | 11 +-
.../server/master/dag/WorkflowDAGBuilder.java | 125 +++++++++
.../server/master/dag/WorkflowDAGFactory.java | 65 +++++
.../server/master/dag/WorkflowEngine.java | 82 ++++++
.../dag/WorkflowExecuteRunnableRepository.java | 52 ++++
.../master/dag/WorkflowExecutionContext.java | 36 ++-
.../WorkflowExecutionContextFactory.java} | 13 +-
.../server/master/dag/WorkflowExecutionDAG.java | 116 +++++++++
.../master/dag/WorkflowExecutionDAGFactory.java | 60 +++++
.../master/dag/WorkflowExecutionRunnable.java | 64 +++++
.../WorkflowExecutionRunnableFactory.java} | 22 +-
.../WorkflowIdentify.java} | 19 +-
.../server/master/events/EventEngine.java | 111 ++++++++
.../server/master/events/EventFirer.java | 95 +++++++
.../EventOperatorManager.java} | 18 +-
.../IAsyncEvent.java} | 12 +-
.../IDelayEvent.java} | 10 +-
.../IEvent.java} | 8 +-
.../IEventFirer.java} | 19 +-
.../IEventOperator.java} | 16 +-
.../IEventOperatorManager.java} | 17 +-
.../IEventRepository.java} | 21 +-
.../ISyncEvent.java} | 9 +-
.../ITaskEvent.java} | 10 +-
.../ITaskEventOperator.java} | 8 +-
.../IWorkflowEvent.java} | 13 +-
.../IWorkflowEventOperator.java} | 11 +-
.../master/events/MemoryEventRepository.java | 60 +++++
.../TaskLogSendToRemoteEvent.java} | 20 +-
.../TaskLogSendToRemoteEventOperator.java} | 22 +-
.../TaskOperationEvent.java} | 28 +-
.../master/events/TaskOperationEventOperator.java | 47 ++++
.../TaskOperationType.java} | 13 +-
.../TaskSuccessEvent.java} | 17 +-
.../master/events/TaskSuccessEventOperator.java | 47 ++++
.../WorkflowFailedEvent.java} | 19 +-
.../master/events/WorkflowFailedEventOperator.java | 57 +++++
.../WorkflowFinalizeEvent.java} | 16 +-
.../WorkflowFinalizeEventOperator.java} | 24 +-
.../WorkflowFinishEvent.java} | 21 +-
.../master/events/WorkflowOperationEvent.java | 51 ++++
.../events/WorkflowOperationEventOperator.java | 87 +++++++
.../WorkflowOperationType.java} | 20 +-
.../WorkflowTimeoutEvent.java} | 17 +-
.../events/WorkflowTimeoutEventOperator.java | 61 +++++
.../WorkflowTriggerNextTaskEvent.java} | 22 +-
.../WorkflowTriggerNextTaskEventOperator.java | 44 ++++
.../WorkflowTriggeredEvent.java} | 17 +-
.../events/WorkflowTriggeredEventOperator.java | 63 +++++
...a => TaskExecuteRunnableNotFoundException.java} | 9 +-
... WorkflowExecuteRunnableNotFoundException.java} | 10 +-
.../master/runner/DefaultTaskExecuteRunnable.java | 3 +-
.../master/runner/TaskExecutionContextFactory.java | 3 +-
.../execute/DefaultTaskExecuteRunnableFactory.java | 18 +-
.../ExceptionUtils.java} | 13 +-
.../server/master/dag/DAGNodeTest.java | 121 +++++++++
.../dag/MockWorkflowExecutionContextFactory.java | 88 +++++++
.../dag/MockWorkflowExecutionRunnableFactory.java} | 15 +-
.../server/master/dag/WorkflowDAGAssertion.java | 171 +++++++++++++
.../server/master/dag/WorkflowDAGBuilderTest.java | 282 +++++++++++++++++++++
.../server/master/dag/WorkflowEngineIT.java} | 8 +-
.../server/master/dag/WorkflowEngineTest.java | 114 +++++++++
.../dag/WorkflowExecutionRunnableAssertions.java | 48 ++++
...kflowExecutionRunnableRepositoryAssertions.java | 43 ++++
.../master/dag/WorkflowExecutionRunnableTest.java | 51 ++++
.../master/events/WorkflowOperationEventTest.java | 46 ++++
.../server/master/utils/ExceptionUtilsTest.java | 18 ++
dolphinscheduler-workflow-engine/README.md | 2 +
dolphinscheduler-workflow-engine/pom.xml | 36 +++
.../dolphinscheduler/workflow/engine/dag/DAG.java | 146 +++++++++++
.../workflow/engine/dag/DAGEdge.java | 53 ++++
.../workflow/engine/dag/DAGNode.java | 92 +++++++
.../workflow/engine/dag/DAGNodeDefinition.java | 19 +-
.../workflow/engine/dag/IDAGNode.java | 16 +-
.../workflow/engine/dag/IDAGNodeAction.java | 19 +-
.../workflow/engine/dag/WorkflowDAG.java | 75 ++++++
.../workflow/engine/dag/WorkflowDAGBuilder.java | 107 ++++++++
.../workflow/engine/engine/DAGEngine.java | 171 +++++++++++++
.../workflow/engine/engine/DAGEngineFactory.java | 20 +-
.../workflow/engine/engine/IDAGEngine.java | 72 ++++++
.../workflow/engine/engine/IDAGEngineFactory.java | 10 +-
.../workflow/engine/engine/IWorkflowEngine.java | 58 +++++
.../engine/engine/IWorkflowEngineFactory.java | 8 +-
.../workflow/engine/engine/WorkflowEngine.java | 82 ++++++
.../engine/engine/WorkflowEngineFactory.java | 12 +-
.../workflow/engine/event/EventEngine.java | 111 ++++++++
.../workflow/engine/event/EventFirer.java | 91 +++++++
.../engine/event/EventOperatorManager.java | 18 +-
.../workflow/engine/event/IAsyncEvent.java | 12 +-
.../workflow/engine/event/IDelayEvent.java | 10 +-
.../workflow/engine/event/IEvent.java | 8 +-
.../workflow/engine/event/IEventFirer.java | 19 +-
.../workflow/engine/event/IEventOperator.java | 16 +-
.../engine/event/IEventOperatorManager.java | 17 +-
.../workflow/engine/event/IEventRepository.java | 21 +-
.../workflow/engine/event/ISyncEvent.java | 9 +-
.../workflow/engine/event/ITaskEvent.java | 10 +-
.../workflow/engine/event/ITaskEventOperator.java | 8 +-
.../workflow/engine/event/IWorkflowEvent.java | 13 +-
.../engine/event/IWorkflowEventOperator.java | 11 +-
.../engine/event/MemoryEventRepository.java | 64 +++++
.../workflow/engine/event/TaskOperationEvent.java | 21 +-
.../engine/event/TaskOperationEventOperator.java | 44 ++++
.../workflow/engine/event/TaskOperationType.java | 13 +-
.../workflow/engine/event/WorkflowFailedEvent.java | 19 +-
.../engine/event/WorkflowFinalizeEvent.java | 16 +-
.../event/WorkflowFinalizeEventOperator.java | 41 +++
.../workflow/engine/event/WorkflowFinishEvent.java | 21 +-
.../engine/event/WorkflowOperationEvent.java | 51 ++++
.../event/WorkflowOperationEventOperator.java | 84 ++++++
.../engine/event/WorkflowOperationType.java | 20 +-
.../WorkflowExecuteRunnableNotFoundException.java | 12 +-
.../workflow/engine/utils/ExceptionUtils.java | 10 +-
.../workflow/IEventfulExecutionRunnable.java | 16 +-
.../engine/workflow/ITaskExecutionContext.java | 8 +-
.../workflow/ITaskExecutionContextFactory.java | 9 +-
.../engine/workflow/ITaskExecutionRunnable.java | 59 +++++
.../workflow/ITaskExecutionRunnableFactory.java | 25 +-
.../workflow/ITaskExecutionRunnableRepository.java | 18 +-
.../workflow/engine/workflow/ITaskInstance.java | 10 +-
.../IWorkflowExecuteRunnableRepository.java | 17 +-
.../engine/workflow/IWorkflowExecutionContext.java | 20 +-
.../engine/workflow/IWorkflowExecutionDAG.java | 71 ++++++
.../workflow/IWorkflowExecutionDAGFactory.java | 8 +-
.../workflow/IWorkflowExecutionRunnable.java | 56 ++++
.../IWorkflowExecutionRunnableFactory.java | 8 +-
.../engine/workflow/IWorkflowInstance.java | 10 +-
...SingletonWorkflowExecuteRunnableRepository.java | 61 +++++
.../engine/workflow/TaskExecutionContext.java | 14 +-
.../workflow/TaskExecutionContextFactory.java | 11 +-
.../engine/workflow/TaskExecutionRunnable.java | 39 ++-
.../workflow/TaskExecutionRunnableFactory.java | 35 +++
.../engine/workflow/WorkflowExecutionContext.java | 23 +-
.../engine/workflow/WorkflowExecutionDAG.java | 124 +++++++++
.../engine/workflow/WorkflowExecutionRunnable.java | 64 +++++
.../workflow/WorkflowExecutionRunnableFactory.java | 18 +-
.../workflow/engine/workflow/WorkflowInstance.java | 20 +-
...orkflowExecuteRunnableRepositoryAssertions.java | 37 +++
.../engine/assertions/WorkflowDAGAssertion.java | 173 +++++++++++++
.../WorkflowExecutionRunnableAssertions.java | 49 ++++
.../workflow/engine/dag/DAGNodeTest.java | 104 ++++++++
.../engine/dag/WorkflowDAGBuilderTest.java | 260 +++++++++++++++++++
.../workflow/engine/engine/WorkflowEngineIT.java | 8 +-
.../workflow/engine/engine/WorkflowEngineTest.java | 105 ++++++++
.../engine/event/WorkflowOperationEventTest.java | 30 +++
.../MockWorkflowExecutionRunnableFactory.java | 46 ++++
pom.xml | 1 +
181 files changed, 6848 insertions(+), 569 deletions(-)
diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessInstance.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessInstance.java
index d8f01f473f..8075dc4091 100644
--- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessInstance.java
+++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessInstance.java
@@ -34,6 +34,7 @@ import java.util.Date;
import java.util.List;
import lombok.AllArgsConstructor;
+import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -44,11 +45,10 @@ import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.google.common.base.Strings;
-/**
- * process instance
- */
-@NoArgsConstructor
@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
@TableName("t_ds_process_instance")
public class ProcessInstance {
diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/ProcessTaskRelationLogDao.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/ProcessTaskRelationLogDao.java
index 8bd12026f0..40955a8a67 100644
--- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/ProcessTaskRelationLogDao.java
+++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/ProcessTaskRelationLogDao.java
@@ -27,6 +27,9 @@ public interface ProcessTaskRelationLogDao extends IDao<ProcessTaskRelationLog>
List<ProcessTaskRelationLog> queryByWorkflowDefinitionCode(long workflowDefinitionCode);
+ List<ProcessTaskRelationLog> queryByWorkflowDefinitionCodeAndVersion(long workflowDefinitionCode,
+ int workflowDefinitionVerison);
+
void deleteByWorkflowDefinitionCode(long workflowDefinitionCode);
/**
diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/impl/ProcessTaskRelationLogDaoImpl.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/impl/ProcessTaskRelationLogDaoImpl.java
index 81c29b89da..b800acb5c7 100644
--- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/impl/ProcessTaskRelationLogDaoImpl.java
+++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/impl/ProcessTaskRelationLogDaoImpl.java
@@ -44,6 +44,12 @@ public class ProcessTaskRelationLogDaoImpl extends BaseDao<ProcessTaskRelationLo
return mybatisMapper.queryByProcessCode(workflowDefinitionCode);
}
+ @Override
+ public List<ProcessTaskRelationLog> queryByWorkflowDefinitionCodeAndVersion(long workflowDefinitionCode,
+ int workflowDefinitionVerison) {
+ return mybatisMapper.queryByProcessCodeAndVersion(workflowDefinitionCode, workflowDefinitionVerison);
+ }
+
@Override
public void deleteByWorkflowDefinitionCode(long workflowDefinitionCode) {
mybatisMapper.deleteByWorkflowDefinitionCode(workflowDefinitionCode);
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/BasicDAG.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/BasicDAG.java
new file mode 100644
index 0000000000..26037eec17
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/BasicDAG.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import lombok.experimental.SuperBuilder;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@SuperBuilder
+public abstract class BasicDAG implements DAG {
+
+ protected Map<String, DAGNode> dagNodeMap;
+
+ @Override
+ public List<DAGNode> getDirectPostNodes(DAGNode dagNode) {
+ final String nodeName = dagNode.getNodeName();
+ if (!dagNodeMap.containsKey(nodeName)) {
+ return Collections.emptyList();
+ }
+ DAGNode node = dagNodeMap.get(nodeName);
+ List<DAGNode> dagNodes = new ArrayList<>();
+ for (DAGEdge edge : node.getOutDegrees()) {
+ if (dagNodeMap.containsKey(edge.getToNodeName())) {
+ dagNodes.add(dagNodeMap.get(edge.getToNodeName()));
+ }
+ }
+ return dagNodes;
+ }
+
+ @Override
+ public List<DAGNode> getDirectPreNodes(DAGNode dagNode) {
+ final String nodeName = dagNode.getNodeName();
+ if (!dagNodeMap.containsKey(nodeName)) {
+ return Collections.emptyList();
+ }
+ DAGNode node = dagNodeMap.get(nodeName);
+ List<DAGNode> dagNodes = new ArrayList<>();
+ for (DAGEdge edge : node.getInDegrees()) {
+ if (dagNodeMap.containsKey(edge.getFromNodeName())) {
+ dagNodes.add(dagNodeMap.get(edge.getFromNodeName()));
+ }
+ }
+ return dagNodes;
+ }
+
+ @Override
+ public DAGNode getDAGNode(String nodeName) {
+ return dagNodeMap.get(nodeName);
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/DAG.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/DAG.java
new file mode 100644
index 0000000000..40dee4f119
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/DAG.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * The Directed Acyclic Graph class.
+ * <p>
+ * The DAG is a directed graph, which contains the nodes and the edges, the nodeName is the unique identifier of the node.
+ * The nodes are the tasks, the edges are the dependencies between the tasks.
+ * The DAG is acyclic, which means there is no cycle in the graph.
+ * The DAG is a directed graph, which means the edges have direction.
+ *
+ */
+public interface DAG {
+
+ /**
+ * Get the direct post node of given dagNode, if the dagNode is null, return the nodes which doesn't have inDegrees.
+ * e.g. The DAG is:
+ * <pre>
+ * {@code
+ * 1 -> 2 -> 3
+ * 4 -> 5
+ * 6
+ * }
+ * </pre>
+ * <li> The post node of 1 is 2.
+ * <li> The post node of 3 is empty.
+ * <li> The post node of null is 1,4,6.
+ *
+ * @param dagNode the node of the DAG, can be null.
+ * @return post node list, sort by priority.
+ */
+ List<DAGNode> getDirectPostNodes(DAGNode dagNode);
+
+ /**
+ * Same with {@link #getDirectPostNodes(DAGNode)}.
+ * <p>
+ * If the dagNodeName is null, return the nodes which doesn't have inDegrees. Otherwise, return the post nodes of
+ * the given dagNodeName. If the dagNodeName is not null and cannot find the node in DAG, throw IllegalArgumentException.
+ *
+ * @param dagNodeName task name, can be null.
+ * @return post task name list, sort by priority.
+ * @throws IllegalArgumentException if the dagNodeName is not null and cannot find the node in DAG.
+ */
+ default List<DAGNode> getDirectPostNodes(String dagNodeName) {
+ DAGNode dagNode = getDAGNode(dagNodeName);
+ if (dagNodeName != null && dagNode == null) {
+ throw new IllegalArgumentException("Cannot find the Node: " + dagNodeName + " in DAG");
+ }
+ return getDirectPostNodes(dagNode);
+ }
+
+ /**
+ * Same with {@link #getDirectPostNodes(String)}. Return the post node names.
+ *
+ * @param dagNodeName task name, can be null.
+ * @return post task name list, sort by priority.
+ * @throws IllegalArgumentException if the dagNodeName is not null and cannot find the node in DAG.
+ */
+ default List<String> getDirectPostNodeNames(String dagNodeName) {
+ DAGNode dagNode = getDAGNode(dagNodeName);
+ if (dagNodeName != null && dagNode == null) {
+ throw new IllegalArgumentException("Cannot find the Node: " + dagNodeName + " in DAG");
+ }
+ return getDirectPostNodes(dagNode).stream().map(DAGNode::getNodeName).collect(Collectors.toList());
+ }
+
+ /**
+ * Get the direct pre node of given dagNode, if the dagNode is null, return the nodes which doesn't have outDegrees.
+ * e.g. The DAG is:
+ * <pre>
+ * {@code
+ * 1 -> 2 -> 3
+ * 4 -> 5
+ * 6
+ * }
+ * </pre>
+ * <li> The pre node of 1 is empty.
+ * <li> The pre node of 3 is 2.
+ * <li> The pre node of null is 3,5,6.
+ *
+ * @param dagNode the node of the DAG, can be null.
+ * @return pre node list, sort by priority.
+ */
+ List<DAGNode> getDirectPreNodes(DAGNode dagNode);
+
+ /**
+ * Same with {@link #getDirectPreNodes(DAGNode)}.
+ * <p>
+ * If the dagNodeName is null, return the nodes which doesn't have outDegrees. Otherwise, return the pre nodes of
+ * the given dagNodeName. If the dagNodeName is not null and cannot find the node in DAG, throw IllegalArgumentException.
+ *
+ * @param dagNodeName task name, can be null.
+ * @return pre task name list, sort by priority.
+ * @throws IllegalArgumentException if the dagNodeName is not null and cannot find the node in DAG.
+ */
+ default List<DAGNode> getDirectPreNodes(String dagNodeName) {
+ DAGNode dagNode = getDAGNode(dagNodeName);
+ if (dagNodeName != null && dagNode == null) {
+ throw new IllegalArgumentException("Cannot find the Node: " + dagNodeName + " in DAG");
+ }
+ return getDirectPreNodes(dagNode);
+ }
+
+ /**
+ * Same with {@link #getDirectPreNodes(String)}. Return the pre node names.
+ *
+ * @param dagNodeName task name, can be null.
+ * @return pre task name list, sort by priority.
+ * @throws IllegalArgumentException if the dagNodeName is not null and cannot find the node in DAG.
+ */
+ default List<String> getDirectPreNodeNames(String dagNodeName) {
+ DAGNode dagNode = getDAGNode(dagNodeName);
+ if (dagNodeName != null && dagNode == null) {
+ throw new IllegalArgumentException("Cannot find the Node: " + dagNodeName + " in DAG");
+ }
+ return getDirectPreNodes(dagNode).stream().map(DAGNode::getNodeName).collect(Collectors.toList());
+ }
+
+ /**
+ * Get the node of the DAG by the node name.
+ *
+ * @param nodeName the node name.
+ * @return the node of the DAG, return null if cannot find the node.
+ */
+ DAGNode getDAGNode(String nodeName);
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/DAGEdge.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/DAGEdge.java
new file mode 100644
index 0000000000..d3ede91fef
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/DAGEdge.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import lombok.Builder;
+import lombok.Data;
+
+/**
+ * The edge of the DAG.
+ * <p>
+ * The edge contains the fromNodeName and the toNodeName, the fromNodeName is the node name of the from node, the toNodeName is the node name of the to node.
+ * <p>
+ * The formNodeName can be null, which means the edge is from the start node of the DAG.
+ * The toNodeName can be null, which means the edge is to the end node of the DAG.
+ * The fromNodeName and the toNodeName cannot be null at the same time.
+ */
+@Data
+@Builder
+public class DAGEdge {
+
+ private String fromNodeName;
+ private String toNodeName;
+
+ public DAGEdge(String fromNodeName, String toNodeName) {
+ if (fromNodeName == null && toNodeName == null) {
+ throw new IllegalArgumentException("fromNodeName and toNodeName cannot be null at the same time"
+ + "fromNodeName: " + fromNodeName + ", toNodeName: " + toNodeName);
+ }
+ if (fromNodeName != null && fromNodeName.equals(toNodeName)) {
+ throw new IllegalArgumentException("fromNodeName and toNodeName cannot be the same"
+ + "fromNodeName: " + fromNodeName + ", toNodeName: " + toNodeName);
+ }
+ this.fromNodeName = fromNodeName;
+ this.toNodeName = toNodeName;
+ }
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/DAGEngine.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/DAGEngine.java
new file mode 100644
index 0000000000..cf1daca1f7
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/DAGEngine.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import org.apache.dolphinscheduler.server.master.events.TaskOperationEvent;
+import org.apache.dolphinscheduler.server.master.events.TaskOperationType;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class DAGEngine implements IDAGEngine {
+
+ private final IWorkflowExecutionContext workflowExecutionContext;
+
+ public DAGEngine(IWorkflowExecutionContext workflowExecutionContext) {
+ this.workflowExecutionContext = workflowExecutionContext;
+ }
+
+ @Override
+ public void triggerNextTasks(String parentTaskNodeName) {
+ workflowExecutionContext.getWorkflowExecutionDAG()
+ .getDirectPostNodeNames(parentTaskNodeName)
+ .forEach(this::triggerTask);
+ }
+
+ @Override
+ public void triggerTask(String taskName) {
+ IWorkflowExecutionDAG workflowExecutionDAG = workflowExecutionContext.getWorkflowExecutionDAG();
+ DAGNode dagNode = workflowExecutionDAG.getDAGNode(taskName);
+ if (dagNode == null) {
+ log.error("Cannot find the DAGNode for task: {}", taskName);
+ return;
+ }
+ // Use condition check?
+ if (!workflowExecutionDAG.isTaskAbleToBeTriggered(taskName)) {
+ log.info("The task: {} is not able to be triggered", taskName);
+ return;
+ }
+
+ if (dagNode.isSkip()) {
+ log.info("The task: {} is skipped", taskName);
+ triggerNextTasks(taskName);
+ return;
+ }
+
+ TaskExecutionRunnable taskExecutionRunnable = workflowExecutionDAG.triggerTask(taskName);
+ TaskOperationEvent taskOperationEvent = TaskOperationEvent.builder()
+ .taskExecutionRunnable(taskExecutionRunnable)
+ .taskOperationType(TaskOperationType.RUN)
+ .build();
+ workflowExecutionContext.getEventRepository().storeEventToTail(taskOperationEvent);
+ }
+
+ @Override
+ public void failoverTask(Integer taskInstanceId) {
+ TaskExecutionRunnable taskExecutionRunnable =
+ workflowExecutionContext.getWorkflowExecutionDAG().getTaskExecutionRunnableById(taskInstanceId);
+ if (taskExecutionRunnable == null) {
+ log.error("Cannot find the ITaskExecutionRunnable for taskInstance: {}", taskInstanceId);
+ return;
+ }
+ TaskOperationEvent taskOperationEvent = TaskOperationEvent.builder()
+ .taskExecutionRunnable(taskExecutionRunnable)
+ .taskOperationType(TaskOperationType.FAILOVER)
+ .build();
+ workflowExecutionContext.getEventRepository().storeEventToTail(taskOperationEvent);
+ }
+
+ @Override
+ public void retryTask(Integer taskInstanceId) {
+ TaskExecutionRunnable taskExecutionRunnable =
+ workflowExecutionContext.getWorkflowExecutionDAG().getTaskExecutionRunnableById(taskInstanceId);
+ if (taskExecutionRunnable == null) {
+ log.error("Cannot find the ITaskExecutionRunnable for taskInstance: {}", taskInstanceId);
+ return;
+ }
+ TaskOperationEvent taskOperationEvent = TaskOperationEvent.builder()
+ .taskExecutionRunnable(taskExecutionRunnable)
+ .taskOperationType(TaskOperationType.RETRY)
+ .build();
+ workflowExecutionContext.getEventRepository().storeEventToTail(taskOperationEvent);
+ }
+
+ @Override
+ public void pauseAllTask() {
+ workflowExecutionContext.getWorkflowExecutionDAG()
+ .getActiveTaskExecutionRunnable()
+ .stream()
+ .map(taskExecutionRunnable -> taskExecutionRunnable.getTaskExecutionContext().getTaskInstance().getId())
+ .forEach(this::pauseTask);
+ }
+
+ @Override
+ public void pauseTask(Integer taskInstanceId) {
+ TaskExecutionRunnable taskExecutionRunnable =
+ workflowExecutionContext.getWorkflowExecutionDAG().getTaskExecutionRunnableById(taskInstanceId);
+ if (taskExecutionRunnable == null) {
+ log.error("Cannot find the ITaskExecutionRunnable for taskInstance: {}", taskInstanceId);
+ return;
+ }
+ TaskOperationEvent taskOperationEvent = TaskOperationEvent.builder()
+ .taskExecutionRunnable(taskExecutionRunnable)
+ .taskOperationType(TaskOperationType.PAUSE)
+ .build();
+ workflowExecutionContext.getEventRepository().storeEventToTail(taskOperationEvent);
+ }
+
+ @Override
+ public void killAllTask() {
+ workflowExecutionContext.getWorkflowExecutionDAG()
+ .getActiveTaskExecutionRunnable()
+ .stream()
+ .map(taskExecutionRunnable -> taskExecutionRunnable.getTaskExecutionContext().getTaskInstance().getId())
+ .forEach(this::killTask);
+ }
+
+ @Override
+ public void killTask(Integer taskInstanceId) {
+ TaskExecutionRunnable taskExecutionRunnable =
+ workflowExecutionContext.getWorkflowExecutionDAG().getTaskExecutionRunnableById(taskInstanceId);
+ if (taskExecutionRunnable == null) {
+ log.error("Cannot find the ITaskExecutionRunnable for taskInstance: {}", taskInstanceId);
+ return;
+ }
+
+ TaskOperationEvent taskOperationEvent = TaskOperationEvent.builder()
+ .taskExecutionRunnable(taskExecutionRunnable)
+ .taskOperationType(TaskOperationType.KILL)
+ .build();
+ workflowExecutionContext.getEventRepository().storeEventToTail(taskOperationEvent);
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/DAGEngineFactory.java
similarity index 68%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/DAGEngineFactory.java
index ac37c94438..43b1a3e5c0 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/DAGEngineFactory.java
@@ -15,12 +15,18 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.extern.slf4j.Slf4j;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class DAGEngineFactory implements IDAGEngineFactory {
+ @Override
+ public IDAGEngine createDAGEngine(IWorkflowExecutionContext workflowExecutionContext) {
+ return new DAGEngine(workflowExecutionContext);
+ }
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/DAGNode.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/DAGNode.java
new file mode 100644
index 0000000000..95bd6c75ba
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/DAGNode.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.List;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+/**
+ * The node of the DAG.
+ * <p>
+ * The node contains the node name, the content of the node, the inDegrees and the outDegrees.
+ * The inDegrees is the edge from other nodes to the current node, the outDegrees is the edge from the current
+ * node to other nodes.
+ */
+@Getter
+@Builder
+@NoArgsConstructor
+public class DAGNode {
+
+ private String nodeName;
+
+ /**
+ * whether the node is skipped, default is false, which means the node is not skipped.
+ * If the node is skipped, the node will not be executed.
+ */
+ @Builder.Default
+ private boolean skip = false;
+
+ private List<DAGEdge> inDegrees;
+ private List<DAGEdge> outDegrees;
+
+ public DAGNode(String nodeName,
+ List<DAGEdge> inDegrees,
+ List<DAGEdge> outDegrees) {
+ this(nodeName, false, inDegrees, outDegrees);
+ }
+
+ public DAGNode(String nodeName,
+ boolean skip,
+ List<DAGEdge> inDegrees,
+ List<DAGEdge> outDegrees) {
+ if (StringUtils.isEmpty(nodeName)) {
+ throw new IllegalArgumentException("nodeName cannot be empty");
+ }
+
+ if (CollectionUtils.isNotEmpty(inDegrees)) {
+ inDegrees.forEach(dagEdge -> {
+ if (!nodeName.equals(dagEdge.getToNodeName())) {
+ throw new IllegalArgumentException(
+ "The toNodeName of inDegree should be the nodeName of the node: "
+ + nodeName + ", inDegree: " + dagEdge);
+ }
+ });
+ }
+
+ if (CollectionUtils.isNotEmpty(outDegrees)) {
+ outDegrees.forEach(dagEdge -> {
+ if (!nodeName.equals(dagEdge.getFromNodeName())) {
+ throw new IllegalArgumentException(
+ "The fromNodeName of outDegree should be the nodeName of the node: "
+ + nodeName + ", outDegree: " + dagEdge);
+ }
+ });
+ }
+
+ this.nodeName = nodeName;
+ this.inDegrees = inDegrees;
+ this.outDegrees = outDegrees;
+ this.skip = skip;
+ }
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IDAGEngine.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IDAGEngine.java
new file mode 100644
index 0000000000..7adc2d9a1e
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IDAGEngine.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+/**
+ * The IDAGEngine is responsible for triggering, killing, pausing, and finalizing task in {@link IWorkflowExecutionDAG}.
+ * <p>All DAG operation should directly use the method in IDAGEngine, new {@link IWorkflowExecutionDAG} should be triggered by new IDAGEngine.
+ */
+public interface IDAGEngine {
+
+ /**
+ * Trigger the tasks which are post of the given task.
+ * <P> If there are no task after the given taskNode, will try to finish the WorkflowExecutionRunnable.
+ * <p> If the
+ *
+ * @param parentTaskNodeName the parent task name
+ */
+ void triggerNextTasks(String parentTaskNodeName);
+
+ /**
+ * Trigger the given task
+ *
+ * @param taskName task name
+ */
+ void triggerTask(String taskName);
+
+ /**
+ * Failover the given task.
+ *
+ * @param taskInstanceId taskInstanceId
+ */
+ void failoverTask(Integer taskInstanceId);
+
+ /**
+ * Retry the given task.
+ *
+ * @param taskInstanceId taskInstanceId
+ */
+ void retryTask(Integer taskInstanceId);
+
+ void pauseAllTask();
+
+ /**
+ * Pause the given task.
+ */
+ void pauseTask(Integer taskInstanceId);
+
+ void killAllTask();
+
+ /**
+ * Kill the given task.
+ */
+ void killTask(Integer taskId);
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IDAGEngineFactory.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IDAGEngineFactory.java
index ac37c94438..0ae555ea8d 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IDAGEngineFactory.java
@@ -15,12 +15,10 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+public interface IDAGEngineFactory {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ IDAGEngine createDAGEngine(IWorkflowExecutionContext workflowExecutionContext);
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IDAGNodeAction.java
similarity index 76%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IDAGNodeAction.java
index ac37c94438..70148bd737 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IDAGNodeAction.java
@@ -15,12 +15,21 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+/**
+ * The IDAGNodeAction represent the action of a DAG node.
+ */
+public interface IDAGNodeAction {
+
+ void run();
+
+ void kill();
+
+ void pause();
+
+ void success();
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ void failure();
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IEventRepositoryFactory.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IEventRepositoryFactory.java
index ac37c94438..630d412856 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IEventRepositoryFactory.java
@@ -15,12 +15,12 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.server.master.events.IEventRepository;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+public interface IEventRepositoryFactory {
+
+ IEventRepository createEventRepository();
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IEventfulExecutionRunnable.java
similarity index 62%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IEventfulExecutionRunnable.java
index ac37c94438..952fa23120 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IEventfulExecutionRunnable.java
@@ -15,12 +15,20 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.server.master.events.IEvent;
+import org.apache.dolphinscheduler.server.master.events.IEventRepository;
- public TaskExecutionContextCreateException(String message) {
- super(message);
+public interface IEventfulExecutionRunnable {
+
+ IEventRepository getEventRepository();
+
+ default void storeEventToTail(IEvent event) {
+ getEventRepository().storeEventToTail(event);
}
+ default void storeEventToHead(IEvent event) {
+ getEventRepository().storeEventToHead(event);
+ }
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/ITaskExecutionContext.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/ITaskExecutionContext.java
index ac37c94438..818cbd0e10 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/ITaskExecutionContext.java
@@ -15,12 +15,12 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.dao.entity.TaskInstance;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+public interface ITaskExecutionContext {
+
+ TaskInstance getTaskInstance();
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/ITaskExecutionContextFactory.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/ITaskExecutionContextFactory.java
index ac37c94438..7c67307371 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/ITaskExecutionContextFactory.java
@@ -15,12 +15,10 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+public interface ITaskExecutionContextFactory {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ ITaskExecutionContext createTaskExecutionContext();
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/ITaskExecutionRunnable.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/ITaskExecutionRunnable.java
new file mode 100644
index 0000000000..dceff535c5
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/ITaskExecutionRunnable.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+/**
+ * The TaskExecutionRunnable represent the running task, it is responsible for operate the task instance. e.g. dispatch, kill, pause.
+ */
+public interface ITaskExecutionRunnable {
+
+ /**
+ * Dispatch the task instance.
+ */
+ void dispatch();
+
+ /**
+ * Run the task instance.
+ */
+ void run();
+
+ /**
+ * Kill the task instance.
+ */
+ void kill();
+
+ /**
+ * Pause the task instance.
+ */
+ void pause();
+
+ /**
+ * Get the task execution context.
+ *
+ * @return the task execution context
+ */
+ TaskExecutionContext getTaskExecutionContext();
+
+ /**
+ * Determine whether the current task can be accessed to the post task.
+ *
+ * @param taskNodeName post task name
+ * @return true if the current task can be accessed to the post task.
+ */
+ boolean canAccessTo(String taskNodeName);
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/ITaskExecutionRunnableFactory.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/ITaskExecutionRunnableFactory.java
index ac37c94438..d1d2cf1ae9 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/ITaskExecutionRunnableFactory.java
@@ -15,12 +15,10 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+public interface ITaskExecutionRunnableFactory {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ TaskExecutionRunnable createTaskExecutionRunnable(ITaskExecutionContext taskExecutionContext);
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/ITaskExecutionRunnableRepository.java
similarity index 60%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/ITaskExecutionRunnableRepository.java
index ac37c94438..094b752cf1 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/ITaskExecutionRunnableRepository.java
@@ -15,12 +15,19 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+import java.util.Collection;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+public interface ITaskExecutionRunnableRepository {
+ void storeTaskExecutionRunnable(TaskExecutionRunnable taskExecutionRunnable);
+
+ TaskExecutionRunnable getTaskExecutionRunnableById(Integer taskInstanceId);
+
+ TaskExecutionRunnable getTaskExecutionRunnableByName(String taskInstanceName);
+
+ Collection<TaskExecutionRunnable> getActiveTaskExecutionRunnable();
+
+ void removeTaskExecutionRunnable(Integer taskInstanceId);
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/ITaskExecutionRunnableRepositoryFactory.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/ITaskExecutionRunnableRepositoryFactory.java
index ac37c94438..6e237a2b06 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/ITaskExecutionRunnableRepositoryFactory.java
@@ -15,12 +15,10 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+public interface ITaskExecutionRunnableRepositoryFactory {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ TaskExecutionRunnableRepository createTaskExecutionRunnableRepository();
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowDAG.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowDAG.java
index ac37c94438..fca3010035 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowDAG.java
@@ -15,12 +15,11 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
-
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+/**
+ * The IWorkflowDAG represent the DAG of a workflow.
+ */
+public interface IWorkflowDAG extends DAG {
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowDAGFactory.java
similarity index 65%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowDAGFactory.java
index ac37c94438..00c9e237da 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowDAGFactory.java
@@ -15,12 +15,21 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.dao.entity.ProcessInstance;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+/**
+ * The Factory used to create {@link IWorkflowDAG}
+ */
+public interface IWorkflowDAGFactory {
+
+ /**
+ * Create the WorkflowDAG
+ *
+ * @param workflowInstance workflowInstance.
+ * @return workflow DAG.
+ */
+ IWorkflowDAG createWorkflowDAG(ProcessInstance workflowInstance);
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowEngine.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowEngine.java
new file mode 100644
index 0000000000..0c3f38dce9
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowEngine.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import org.apache.dolphinscheduler.server.master.exception.WorkflowExecuteRunnableNotFoundException;
+
+/**
+ * The WorkflowEngine is responsible for starting, stopping, pausing, and finalizing workflows.
+ */
+public interface IWorkflowEngine {
+
+ /**
+ * Trigger a workflow to start.
+ *
+ * @param workflowExecuteRunnable the workflow to start
+ */
+ void triggerWorkflow(IWorkflowExecutionRunnable workflowExecuteRunnable);
+
+ /**
+ * Pause a workflow instance.
+ *
+ * @param workflowInstanceId the ID of the workflow to pause
+ * @throws WorkflowExecuteRunnableNotFoundException if the workflow is not found
+ */
+ void pauseWorkflow(Integer workflowInstanceId);
+
+ /**
+ * Kill a workflow instance.
+ *
+ * @param workflowInstanceId the ID of the workflow to stop
+ * @throws WorkflowExecuteRunnableNotFoundException if the workflow is not found
+ */
+ void killWorkflow(Integer workflowInstanceId);
+
+ /**
+ * Finalize a workflow instance. Once a workflow has been finalized, then it cannot receive new operation, and will be removed from memory.
+ *
+ * @param workflowInstanceId the ID of the workflow to finalize
+ */
+ void finalizeWorkflow(Integer workflowInstanceId);
+
+}
diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/ProcessTaskRelationLogDao.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowExecutionContext.java
similarity index 53%
copy from dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/ProcessTaskRelationLogDao.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowExecutionContext.java
index 8bd12026f0..53bcf3555b 100644
--- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/ProcessTaskRelationLogDao.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowExecutionContext.java
@@ -15,25 +15,32 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.dao.repository;
+package org.apache.dolphinscheduler.server.master.dag;
-import org.apache.dolphinscheduler.dao.entity.ProcessTaskRelationLog;
-
-import org.apache.ibatis.annotations.Param;
+import org.apache.dolphinscheduler.dao.entity.ProcessDefinition;
+import org.apache.dolphinscheduler.dao.entity.ProcessInstance;
+import org.apache.dolphinscheduler.server.master.events.IEventRepository;
import java.util.List;
-public interface ProcessTaskRelationLogDao extends IDao<ProcessTaskRelationLog> {
+public interface IWorkflowExecutionContext {
+
+ IWorkflowExecutionDAG getWorkflowExecutionDAG();
+
+ ProcessInstance getWorkflowInstance();
+
+ ProcessDefinition getWorkflowDefinition();
+
+ List<String> getBeginNodeNames();
+
+ IEventRepository getEventRepository();
- List<ProcessTaskRelationLog> queryByWorkflowDefinitionCode(long workflowDefinitionCode);
+ default int getWorkflowInstanceId() {
+ return getWorkflowInstance().getId();
+ }
- void deleteByWorkflowDefinitionCode(long workflowDefinitionCode);
+ default String getWorkflowInstanceName() {
+ return getWorkflowInstance().getName();
+ }
- /**
- * batch insert process task relation
- *
- * @param taskRelationList taskRelationList
- * @return int
- */
- int batchInsert(@Param("taskRelationList") List<ProcessTaskRelationLog> taskRelationList);
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowExecutionDAG.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowExecutionDAG.java
new file mode 100644
index 0000000000..33e597cf2e
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowExecutionDAG.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import java.util.List;
+
+/**
+ * The WorkflowExecutionDAG represent the running workflow DAG.
+ */
+public interface IWorkflowExecutionDAG extends DAG {
+
+ /**
+ * Trigger the taskNode by given taskName.
+ *
+ * @param taskName taskNodeName
+ * @return TaskExecutionRunnable
+ */
+ TaskExecutionRunnable triggerTask(String taskName);
+
+ /**
+ * Get TaskExecutionRunnable by given TaskInstanceId.
+ *
+ * @param taskInstanceId taskInstanceId.
+ * @return TaskExecutionRunnable
+ */
+ TaskExecutionRunnable getTaskExecutionRunnableById(Integer taskInstanceId);
+
+ /**
+ * Get TaskExecutionRunnable by given taskName.
+ *
+ * @param taskName task name.
+ * @return TaskExecutionRunnable
+ */
+ TaskExecutionRunnable getTaskExecutionRunnableByName(String taskName);
+
+ /**
+ * Get TaskExecutionRunnable which is not finished.
+ *
+ * @return TaskExecutionRunnable
+ */
+ List<TaskExecutionRunnable> getActiveTaskExecutionRunnable();
+
+ /**
+ * Get the direct pre TaskExecutionRunnable of the given taskName.
+ *
+ * @param taskName task name.
+ * @return TaskExecutionRunnable
+ */
+ List<TaskExecutionRunnable> getDirectPreTaskExecutionRunnable(String taskName);
+
+ /**
+ * Check whether the taskNode is ready to run.
+ *
+ * @param taskName taskNodeName
+ * @return true if the taskNode is ready to run.
+ */
+ boolean isTaskAbleToBeTriggered(String taskName);
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowExecutionDAGFactory.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowExecutionDAGFactory.java
index ac37c94438..429987ca1f 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowExecutionDAGFactory.java
@@ -15,12 +15,9 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
-
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+public interface IWorkflowExecutionDAGFactory {
+ IWorkflowExecutionDAG createWorkflowExecutionDAG();
}
diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/ProcessTaskRelationLogDao.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowExecutionRunnable.java
similarity index 50%
copy from dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/ProcessTaskRelationLogDao.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowExecutionRunnable.java
index 8bd12026f0..d0a641239d 100644
--- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/ProcessTaskRelationLogDao.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/IWorkflowExecutionRunnable.java
@@ -15,25 +15,40 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.dao.repository;
+package org.apache.dolphinscheduler.server.master.dag;
-import org.apache.dolphinscheduler.dao.entity.ProcessTaskRelationLog;
-
-import org.apache.ibatis.annotations.Param;
+/**
+ * The IWorkflowExecuteRunnable represent a running workflow instance, it is responsible for operate the workflow instance. e.g. start, kill, pause.
+ */
+public interface IWorkflowExecutionRunnable extends IEventfulExecutionRunnable {
-import java.util.List;
+ /**
+ * Start the workflow instance.
+ */
+ void start();
-public interface ProcessTaskRelationLogDao extends IDao<ProcessTaskRelationLog> {
+ /**
+ * Kill the workflow instance.
+ */
+ void kill();
- List<ProcessTaskRelationLog> queryByWorkflowDefinitionCode(long workflowDefinitionCode);
+ /**
+ * Pause the workflow instance.
+ */
+ void pause();
- void deleteByWorkflowDefinitionCode(long workflowDefinitionCode);
+ /**
+ * Get the workflow execution context.
+ *
+ * @return the workflow execution context
+ */
+ IWorkflowExecutionContext getWorkflowExecutionContext();
/**
- * batch insert process task relation
+ * Get the {@link IDAGEngine} which used to execute the dag of the workflow instance.
*
- * @param taskRelationList taskRelationList
- * @return int
+ * @return dag engine.
*/
- int batchInsert(@Param("taskRelationList") List<ProcessTaskRelationLog> taskRelationList);
+ IDAGEngine getDagEngine();
+
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/MemoryEventRepositoryFactory.java
similarity index 61%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/MemoryEventRepositoryFactory.java
index ac37c94438..e61351f472 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/MemoryEventRepositoryFactory.java
@@ -15,12 +15,21 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.server.master.events.IEventRepository;
+import org.apache.dolphinscheduler.server.master.events.MemoryEventRepository;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.stereotype.Component;
+@Slf4j
+@Component
+public class MemoryEventRepositoryFactory implements IEventRepositoryFactory {
+
+ @Override
+ public IEventRepository createEventRepository() {
+ return new MemoryEventRepository();
+ }
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/TaskExecutionContext.java
similarity index 67%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/TaskExecutionContext.java
index ac37c94438..bf079e861f 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/TaskExecutionContext.java
@@ -15,12 +15,21 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.dao.entity.TaskInstance;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class TaskExecutionContext implements ITaskExecutionContext {
+
+ private TaskInstance taskInstance;
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/TaskExecutionRunnable.java
similarity index 53%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/TaskExecutionRunnable.java
index ac37c94438..0f21592b26 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/TaskExecutionRunnable.java
@@ -15,12 +15,42 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.Builder;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
- public TaskExecutionContextCreateException(String message) {
- super(message);
+@Slf4j
+@Getter
+@Builder
+public class TaskExecutionRunnable implements ITaskExecutionRunnable {
+
+ private TaskExecutionContext taskExecutionContext;
+
+ @Override
+ public void dispatch() {
+ // todo: check if the operation is valid
+ }
+
+ @Override
+ public void run() {
+
+ }
+
+ @Override
+ public void kill() {
+ // todo: check if the operation is valid
+ }
+
+ @Override
+ public void pause() {
+ // todo: check if the operation is valid
+ }
+
+ @Override
+ public boolean canAccessTo(String postTaskNodeName) {
+ return false;
}
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/TaskExecutionRunnableRepository.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/TaskExecutionRunnableRepository.java
new file mode 100644
index 0000000000..eb8799c212
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/TaskExecutionRunnableRepository.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+/**
+ * Use to store the TaskExecutionRunnable of a DAG.
+ */
+public class TaskExecutionRunnableRepository implements ITaskExecutionRunnableRepository {
+
+ private final Map<Integer, TaskExecutionRunnable> taskExecuteRunnableMap = new ConcurrentHashMap<>();
+
+ private final Map<String, TaskExecutionRunnable> taskExecuteRunnableNameMap = new ConcurrentHashMap<>();
+
+ @Override
+ public void storeTaskExecutionRunnable(TaskExecutionRunnable taskExecutionRunnable) {
+ taskExecuteRunnableMap.put(taskExecutionRunnable.getTaskExecutionContext().getTaskInstance().getId(),
+ taskExecutionRunnable);
+ taskExecuteRunnableNameMap.put(taskExecutionRunnable.getTaskExecutionContext().getTaskInstance().getName(),
+ taskExecutionRunnable);
+ }
+
+ public TaskExecutionRunnable getTaskExecutionRunnableById(Integer taskInstanceId) {
+ return taskExecuteRunnableMap.get(taskInstanceId);
+ }
+
+ @Override
+ public TaskExecutionRunnable getTaskExecutionRunnableByName(String taskInstanceName) {
+ return taskExecuteRunnableNameMap.get(taskInstanceName);
+ }
+
+ public Collection<TaskExecutionRunnable> getActiveTaskExecutionRunnable() {
+ return taskExecuteRunnableMap.values()
+ .stream()
+ .filter(taskExecutionRunnable -> {
+ return taskExecutionRunnable.getTaskExecutionContext().getTaskInstance().getState().isRunning();
+ })
+ .collect(Collectors.toList());
+ }
+
+ public void removeTaskExecutionRunnable(Integer taskInstanceId) {
+ TaskExecutionRunnable taskExecutionRunnable = taskExecuteRunnableMap.remove(taskInstanceId);
+ if (taskExecutionRunnable != null) {
+ taskExecuteRunnableNameMap
+ .remove(taskExecutionRunnable.getTaskExecutionContext().getTaskInstance().getName());
+ }
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/TaskExecutionRunnableRepositoryFactory.java
similarity index 66%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/TaskExecutionRunnableRepositoryFactory.java
index ac37c94438..55ff26916d 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/TaskExecutionRunnableRepositoryFactory.java
@@ -15,12 +15,18 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.extern.slf4j.Slf4j;
- public TaskExecutionContextCreateException(String message) {
- super(message);
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class TaskExecutionRunnableRepositoryFactory implements ITaskExecutionRunnableRepositoryFactory {
+
+ public TaskExecutionRunnableRepository createTaskExecutionRunnableRepository() {
+ return new TaskExecutionRunnableRepository();
}
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/TaskExecutionValve.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/TaskExecutionValve.java
index ac37c94438..2bf015992d 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/TaskExecutionValve.java
@@ -15,12 +15,13 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+/**
+ * Used to judge whether the task can be executed.
+ */
+public interface TaskExecutionValve {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ boolean canOpen(TaskExecutionRunnable preTask, String postTask);
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/TaskIdentify.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/TaskIdentify.java
index ac37c94438..d9dd0d0b1c 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/TaskIdentify.java
@@ -15,12 +15,8 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
-
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+public class TaskIdentify {
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowDAG.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowDAG.java
index ac37c94438..c48785b795 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowDAG.java
@@ -15,12 +15,13 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.experimental.SuperBuilder;
+import lombok.extern.slf4j.Slf4j;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+@Slf4j
+@SuperBuilder
+public class WorkflowDAG extends BasicDAG implements IWorkflowDAG {
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowDAGBuilder.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowDAGBuilder.java
new file mode 100644
index 0000000000..1906afc7fb
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowDAGBuilder.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import org.apache.dolphinscheduler.common.enums.Flag;
+import org.apache.dolphinscheduler.dao.entity.ProcessTaskRelationLog;
+import org.apache.dolphinscheduler.dao.entity.TaskDefinitionLog;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Used to build WorkflowDAG, you need to add TaskNode first, then add TaskEdge.
+ * After adding all the TaskNodes and TaskEdges, you can call the build method to get the WorkflowDAG.
+ * <p>
+ * Example:
+ * <pre>
+ * {@code
+ * WorkflowDAG workflowDAG = WorkflowDAGBuilder.newBuilder()
+ * .addTaskNode(taskNodeA)
+ * .addTaskNode(taskNodeB)
+ * .addTaskNode(taskNodeC)
+ * .addTaskEdge(edgeAB)
+ * .addTaskEdge(edgeBC)
+ * .build();
+ * }
+ * </pre>
+ */
+public class WorkflowDAGBuilder {
+
+ private final Map<String, DAGNode> taskNameMap;
+
+ private final Map<Long, DAGNode> taskCodeMap;
+
+ private WorkflowDAGBuilder() {
+ this.taskCodeMap = new HashMap<>();
+ this.taskNameMap = new HashMap<>();
+ }
+
+ public static WorkflowDAGBuilder newBuilder() {
+ return new WorkflowDAGBuilder();
+ }
+
+ public WorkflowDAGBuilder addTaskNodes(List<TaskDefinitionLog> taskDefinitionList) {
+ taskDefinitionList.forEach(this::addTaskNode);
+ return this;
+ }
+
+ public WorkflowDAGBuilder addTaskNode(TaskDefinitionLog taskDefinition) {
+ String taskName = taskDefinition.getName();
+ long taskCode = taskDefinition.getCode();
+ if (taskCodeMap.containsKey(taskCode)) {
+ throw new IllegalArgumentException("TaskNode with code " + taskCode + " already exists");
+ }
+ if (taskNameMap.containsKey(taskName)) {
+ throw new IllegalArgumentException("TaskNode with name " + taskName + " already exists");
+ }
+
+ DAGNode taskNode = DAGNode.builder()
+ .nodeName(taskName)
+ .inDegrees(new ArrayList<>())
+ .outDegrees(new ArrayList<>())
+ .skip(Flag.NO.equals(taskDefinition.getFlag()))
+ .build();
+ taskNameMap.put(taskName, taskNode);
+ taskCodeMap.put(taskCode, taskNode);
+ return this;
+ }
+
+ public WorkflowDAGBuilder addTaskEdges(List<ProcessTaskRelationLog> processTaskRelations) {
+ processTaskRelations.forEach(this::addTaskEdge);
+ return this;
+ }
+
+ public WorkflowDAGBuilder addTaskEdge(ProcessTaskRelationLog processTaskRelation) {
+ long preTaskCode = processTaskRelation.getPreTaskCode();
+ long postTaskCode = processTaskRelation.getPostTaskCode();
+
+ if (taskCodeMap.containsKey(preTaskCode)) {
+ DAGNode fromTask = taskCodeMap.get(preTaskCode);
+ if (taskCodeMap.containsKey(postTaskCode)) {
+ DAGNode toTask = taskCodeMap.get(postTaskCode);
+ DAGEdge edge = DAGEdge.builder()
+ .fromNodeName(fromTask.getNodeName())
+ .toNodeName(toTask.getNodeName())
+ .build();
+ if (fromTask.getOutDegrees().contains(edge)) {
+ throw new IllegalArgumentException(
+ "Edge from " + fromTask.getNodeName() + " to " + toTask.getNodeName() + " already exists");
+ }
+ fromTask.getOutDegrees().add(edge);
+ if (toTask.getInDegrees().contains(edge)) {
+ throw new IllegalArgumentException(
+ "Edge from " + fromTask.getNodeName() + " to " + toTask.getNodeName() + " already exists");
+ }
+ toTask.getInDegrees().add(edge);
+ }
+ }
+ return this;
+ }
+
+ public WorkflowDAG build() {
+ return WorkflowDAG.builder()
+ .dagNodeMap(taskNameMap)
+ .build();
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowDAGFactory.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowDAGFactory.java
new file mode 100644
index 0000000000..de743c2851
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowDAGFactory.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import org.apache.dolphinscheduler.dao.entity.ProcessInstance;
+import org.apache.dolphinscheduler.dao.entity.ProcessTaskRelationLog;
+import org.apache.dolphinscheduler.dao.entity.TaskDefinitionLog;
+import org.apache.dolphinscheduler.dao.repository.ProcessTaskRelationLogDao;
+import org.apache.dolphinscheduler.dao.repository.TaskDefinitionLogDao;
+
+import java.util.List;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class WorkflowDAGFactory implements IWorkflowDAGFactory {
+
+ @Autowired
+ private TaskDefinitionLogDao taskDefinitionLogDao;
+
+ @Autowired
+ private ProcessTaskRelationLogDao processTaskRelationLogDao;
+
+ @Override
+ public IWorkflowDAG createWorkflowDAG(ProcessInstance processInstance) {
+ Long workflowDefinitionCode = processInstance.getProcessDefinitionCode();
+ Integer workflowDefinitionVersion = processInstance.getProcessDefinitionVersion();
+ List<TaskDefinitionLog> taskDefinitions = queryTaskNodes(workflowDefinitionCode, workflowDefinitionVersion);
+ List<ProcessTaskRelationLog> taskRelations = queryTaskEdges(workflowDefinitionCode, workflowDefinitionVersion);
+ return WorkflowDAGBuilder.newBuilder()
+ .addTaskNodes(taskDefinitions)
+ .addTaskEdges(taskRelations)
+ .build();
+ }
+
+ private List<TaskDefinitionLog> queryTaskNodes(Long workflowDefinitionCode, Integer workflowDefinitionVersion) {
+ return taskDefinitionLogDao.queryByWorkflowDefinitionCodeAndVersion(workflowDefinitionCode,
+ workflowDefinitionVersion);
+ }
+
+ private List<ProcessTaskRelationLog> queryTaskEdges(Long workflowDefinitionCode,
+ Integer workflowDefinitionVersion) {
+ return processTaskRelationLogDao.queryByWorkflowDefinitionCodeAndVersion(workflowDefinitionCode,
+ workflowDefinitionVersion);
+ }
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowEngine.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowEngine.java
new file mode 100644
index 0000000000..550c837ffc
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowEngine.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import org.apache.dolphinscheduler.server.master.events.WorkflowOperationEvent;
+import org.apache.dolphinscheduler.server.master.exception.WorkflowExecuteRunnableNotFoundException;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class WorkflowEngine implements IWorkflowEngine {
+
+ private final WorkflowExecuteRunnableRepository workflowExecuteRunnableRepository;
+
+ public WorkflowEngine(WorkflowExecuteRunnableRepository workflowExecuteRunnableRepository) {
+ this.workflowExecuteRunnableRepository = workflowExecuteRunnableRepository;
+ }
+
+ @Override
+ public void triggerWorkflow(IWorkflowExecutionRunnable workflowExecuteRunnable) {
+ IWorkflowExecutionContext workflowExecutionContext = workflowExecuteRunnable.getWorkflowExecutionContext();
+ Integer workflowInstanceId = workflowExecutionContext.getWorkflowInstanceId();
+ log.info("Triggering WorkflowExecutionRunnable: {}", workflowExecutionContext.getWorkflowInstanceName());
+ workflowExecuteRunnableRepository.storeWorkflowExecutionRunnable(workflowExecuteRunnable);
+ workflowExecuteRunnable.storeEventToTail(WorkflowOperationEvent.triggerEvent(workflowInstanceId));
+ }
+
+ @Override
+ public void pauseWorkflow(Integer workflowInstanceId) {
+ IWorkflowExecutionRunnable workflowExecuteRunnable =
+ workflowExecuteRunnableRepository.getWorkflowExecutionRunnableById(workflowInstanceId);
+ if (workflowExecuteRunnable == null) {
+ throw new WorkflowExecuteRunnableNotFoundException(workflowInstanceId);
+ }
+ log.info("Pausing WorkflowExecutionRunnable: {}",
+ workflowExecuteRunnable.getWorkflowExecutionContext().getWorkflowInstanceName());
+ workflowExecuteRunnable.storeEventToTail(WorkflowOperationEvent.pauseEvent(workflowInstanceId));
+ }
+
+ @Override
+ public void killWorkflow(Integer workflowInstanceId) {
+ IWorkflowExecutionRunnable workflowExecuteRunnable =
+ workflowExecuteRunnableRepository.getWorkflowExecutionRunnableById(workflowInstanceId);
+ if (workflowExecuteRunnable == null) {
+ throw new WorkflowExecuteRunnableNotFoundException(workflowInstanceId);
+ }
+ log.info("Killing WorkflowExecutionRunnable: {}",
+ workflowExecuteRunnable.getWorkflowExecutionContext().getWorkflowInstanceName());
+ workflowExecuteRunnable.storeEventToTail(WorkflowOperationEvent.killEvent(workflowInstanceId));
+ }
+
+ @Override
+ public void finalizeWorkflow(Integer workflowInstanceId) {
+ IWorkflowExecutionRunnable workflowExecutionRunnable =
+ workflowExecuteRunnableRepository.getWorkflowExecutionRunnableById(workflowInstanceId);
+ if (workflowExecutionRunnable == null) {
+ return;
+ }
+ log.info("Finalizing WorkflowExecutionRunnable: {}",
+ workflowExecutionRunnable.getWorkflowExecutionContext().getWorkflowInstanceName());
+ workflowExecuteRunnableRepository.removeWorkflowExecutionRunnable(workflowInstanceId);
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecuteRunnableRepository.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecuteRunnableRepository.java
new file mode 100644
index 0000000000..78beaa44e7
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecuteRunnableRepository.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class WorkflowExecuteRunnableRepository {
+
+ private final Map<Integer, IWorkflowExecutionRunnable> workflowExecutionRunnableMap = new ConcurrentHashMap<>();
+
+ public void storeWorkflowExecutionRunnable(IWorkflowExecutionRunnable workflowExecutionRunnable) {
+ workflowExecutionRunnableMap.put(
+ workflowExecutionRunnable.getWorkflowExecutionContext().getWorkflowInstanceId(),
+ workflowExecutionRunnable);
+ }
+
+ public IWorkflowExecutionRunnable getWorkflowExecutionRunnableById(Integer workflowInstanceId) {
+ return workflowExecutionRunnableMap.get(workflowInstanceId);
+ }
+
+ public Collection<IWorkflowExecutionRunnable> getActiveWorkflowExecutionRunnable() {
+ return workflowExecutionRunnableMap.values();
+ }
+
+ public void removeWorkflowExecutionRunnable(Integer workflowInstanceId) {
+ workflowExecutionRunnableMap.remove(workflowInstanceId);
+ }
+
+}
diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/ProcessTaskRelationLogDao.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionContext.java
similarity index 52%
copy from dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/ProcessTaskRelationLogDao.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionContext.java
index 8bd12026f0..be9c165882 100644
--- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/ProcessTaskRelationLogDao.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionContext.java
@@ -15,25 +15,33 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.dao.repository;
+package org.apache.dolphinscheduler.server.master.dag;
-import org.apache.dolphinscheduler.dao.entity.ProcessTaskRelationLog;
-
-import org.apache.ibatis.annotations.Param;
+import org.apache.dolphinscheduler.dao.entity.ProcessDefinition;
+import org.apache.dolphinscheduler.dao.entity.ProcessInstance;
+import org.apache.dolphinscheduler.server.master.events.IEventRepository;
import java.util.List;
-public interface ProcessTaskRelationLogDao extends IDao<ProcessTaskRelationLog> {
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WorkflowExecutionContext implements IWorkflowExecutionContext {
+
+ private ProcessDefinition workflowDefinition;
+
+ private ProcessInstance workflowInstance;
+
+ private List<String> beginNodeNames;
- List<ProcessTaskRelationLog> queryByWorkflowDefinitionCode(long workflowDefinitionCode);
+ private IWorkflowExecutionDAG workflowExecutionDAG;
- void deleteByWorkflowDefinitionCode(long workflowDefinitionCode);
+ private IEventRepository eventRepository;
- /**
- * batch insert process task relation
- *
- * @param taskRelationList taskRelationList
- * @return int
- */
- int batchInsert(@Param("taskRelationList") List<ProcessTaskRelationLog> taskRelationList);
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionContextFactory.java
similarity index 71%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionContextFactory.java
index ac37c94438..69ad93b106 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionContextFactory.java
@@ -15,12 +15,17 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.dao.entity.Command;
- public TaskExecutionContextCreateException(String message) {
- super(message);
+import org.springframework.stereotype.Component;
+
+@Component
+public class WorkflowExecutionContextFactory {
+
+ public WorkflowExecutionContext createWorkflowExecutionContext(Command command) {
+ return null;
}
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionDAG.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionDAG.java
new file mode 100644
index 0000000000..86c690d44f
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionDAG.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import lombok.experimental.SuperBuilder;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * The WorkflowExecutionDAG represent a running workflow instance DAG.
+ */
+@Slf4j
+@SuperBuilder
+public class WorkflowExecutionDAG implements IWorkflowExecutionDAG {
+
+ private final ITaskExecutionContextFactory taskExecutionContextFactory;
+
+ private final ITaskExecutionRunnableFactory taskExecutionRunnableFactory;
+
+ private final TaskExecutionRunnableRepository taskExecutionRunnableRepository;
+
+ private final IWorkflowDAG workflowDAG;
+
+ @Override
+ public TaskExecutionRunnable triggerTask(String taskName) {
+ DAGNode dagNode = getDAGNode(taskName);
+ if (dagNode == null) {
+ throw new IllegalArgumentException("Cannot find the DAGNode for task: " + taskName);
+ }
+ // Create task execution context
+ taskExecutionContextFactory.createTaskExecutionContext();
+ TaskExecutionRunnable taskExecutionRunnable = taskExecutionRunnableFactory.createTaskExecutionRunnable(null);
+ taskExecutionRunnableRepository.storeTaskExecutionRunnable(taskExecutionRunnable);
+ return taskExecutionRunnable;
+ }
+
+ @Override
+ public TaskExecutionRunnable getTaskExecutionRunnableById(Integer taskInstanceId) {
+ return taskExecutionRunnableRepository.getTaskExecutionRunnableById(taskInstanceId);
+ }
+
+ @Override
+ public TaskExecutionRunnable getTaskExecutionRunnableByName(String taskName) {
+ return taskExecutionRunnableRepository.getTaskExecutionRunnableByName(taskName);
+ }
+
+ @Override
+ public List<TaskExecutionRunnable> getActiveTaskExecutionRunnable() {
+ return new ArrayList<>(taskExecutionRunnableRepository.getActiveTaskExecutionRunnable());
+ }
+
+ @Override
+ public List<TaskExecutionRunnable> getDirectPreTaskExecutionRunnable(String taskName) {
+ return getDirectPreNodeNames(taskName)
+ .stream()
+ .map(taskExecutionRunnableRepository::getTaskExecutionRunnableByName)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public boolean isTaskAbleToBeTriggered(String taskNodeName) {
+ // todo: Check whether the workflow instance is finished or ready to finish.
+ List<DAGNode> directPreNodes = getDirectPreNodes(taskNodeName);
+ if (log.isDebugEnabled()) {
+ log.debug("Begin to check whether the task {} is able to be triggered.", taskNodeName);
+ log.debug("Task {} directly dependent on the task: {}.", taskNodeName,
+ directPreNodes.stream().map(DAGNode::getNodeName).collect(Collectors.toList()));
+ }
+ for (DAGNode directPreNode : directPreNodes) {
+ if (directPreNode.isSkip()) {
+ log.debug("The task {} is skipped.", directPreNode.getNodeName());
+ continue;
+ }
+ TaskExecutionRunnable taskExecutionRunnable = getTaskExecutionRunnableByName(directPreNode.getNodeName());
+ if (taskExecutionRunnable == null || taskExecutionRunnable.canAccessTo(taskNodeName)) {
+ log.debug("The task {} is not finished or not able to access to the task {}.",
+ directPreNode.getNodeName(), taskNodeName);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public List<DAGNode> getDirectPostNodes(DAGNode dagNode) {
+ return workflowDAG.getDirectPostNodes(dagNode);
+ }
+
+ @Override
+ public List<DAGNode> getDirectPreNodes(DAGNode dagNode) {
+ return workflowDAG.getDirectPreNodes(dagNode);
+ }
+
+ @Override
+ public DAGNode getDAGNode(String nodeName) {
+ return workflowDAG.getDAGNode(nodeName);
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionDAGFactory.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionDAGFactory.java
new file mode 100644
index 0000000000..fa1e897c20
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionDAGFactory.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class WorkflowExecutionDAGFactory implements IWorkflowExecutionDAGFactory {
+
+ @Autowired
+ private ITaskExecutionRunnableRepositoryFactory taskExecutionRunnableRepositoryFactory;
+
+ @Autowired
+ private ITaskExecutionRunnableFactory taskExecutionRunnableFactory;
+
+ @Autowired
+ private ITaskExecutionContextFactory taskExecutionContextFactory;
+
+ @Override
+ public IWorkflowExecutionDAG createWorkflowExecutionDAG() {
+ // todo:
+ TaskExecutionRunnableRepository taskExecutionRunnableRepository =
+ taskExecutionRunnableRepositoryFactory.createTaskExecutionRunnableRepository();
+ loadTheHistoryTaskExecutionRunnable()
+ .forEach(taskExecutionRunnableRepository::storeTaskExecutionRunnable);
+
+ return WorkflowExecutionDAG.builder()
+ .taskExecutionContextFactory(taskExecutionContextFactory)
+ .taskExecutionRunnableFactory(taskExecutionRunnableFactory)
+ .taskExecutionRunnableRepository(taskExecutionRunnableRepository)
+ .workflowDAG(null)
+ .build();
+ }
+
+ private List<TaskExecutionRunnable> loadTheHistoryTaskExecutionRunnable() {
+ return new ArrayList<>();
+ }
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionRunnable.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionRunnable.java
new file mode 100644
index 0000000000..1c9b4208e7
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionRunnable.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import org.apache.dolphinscheduler.server.master.events.IEventRepository;
+import org.apache.dolphinscheduler.server.master.events.WorkflowTriggeredEvent;
+
+import org.apache.commons.collections4.CollectionUtils;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Getter
+@Builder
+@AllArgsConstructor
+public class WorkflowExecutionRunnable implements IWorkflowExecutionRunnable {
+
+ private final IWorkflowExecutionContext workflowExecutionContext;
+
+ private final IDAGEngine dagEngine;
+
+ public void start() {
+ if (CollectionUtils.isEmpty(workflowExecutionContext.getBeginNodeNames())) {
+ dagEngine.triggerNextTasks(null);
+ } else {
+ workflowExecutionContext.getBeginNodeNames().forEach(dagEngine::triggerTask);
+ }
+ getEventRepository()
+ .storeEventToTail(new WorkflowTriggeredEvent(workflowExecutionContext.getWorkflowInstance().getId()));
+ }
+
+ @Override
+ public void pause() {
+ dagEngine.pauseAllTask();
+ }
+
+ @Override
+ public void kill() {
+ dagEngine.killAllTask();
+ }
+
+ @Override
+ public IEventRepository getEventRepository() {
+ return workflowExecutionContext.getEventRepository();
+ }
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionRunnableFactory.java
similarity index 52%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionRunnableFactory.java
index ac37c94438..4d3f766725 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionRunnableFactory.java
@@ -15,12 +15,26 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.extern.slf4j.Slf4j;
- public TaskExecutionContextCreateException(String message) {
- super(message);
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class WorkflowExecutionRunnableFactory {
+
+ @Autowired
+ private IDAGEngineFactory dagEngineFactory;
+
+ public WorkflowExecutionRunnable createWorkflowExecuteRunnable(IWorkflowExecutionContext workflowExecutionContext) {
+ IDAGEngine dagEngine = dagEngineFactory.createDAGEngine(workflowExecutionContext);
+ return WorkflowExecutionRunnable.builder()
+ .workflowExecutionContext(workflowExecutionContext)
+ .dagEngine(dagEngine)
+ .build();
}
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowIdentify.java
similarity index 71%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowIdentify.java
index ac37c94438..0b7981199a 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/dag/WorkflowIdentify.java
@@ -15,12 +15,21 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WorkflowIdentify {
+
+ private long workflowCode;
+
+ private int workflowVersion;
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/EventEngine.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/EventEngine.java
new file mode 100644
index 0000000000..f614a59caf
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/EventEngine.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.events;
+
+import org.apache.dolphinscheduler.common.thread.BaseDaemonThread;
+import org.apache.dolphinscheduler.common.thread.ThreadUtils;
+import org.apache.dolphinscheduler.plugin.task.api.utils.LogUtils;
+import org.apache.dolphinscheduler.server.master.dag.IWorkflowExecutionContext;
+import org.apache.dolphinscheduler.server.master.dag.IWorkflowExecutionRunnable;
+import org.apache.dolphinscheduler.server.master.dag.WorkflowExecuteRunnableRepository;
+
+import org.apache.commons.lang3.time.StopWatch;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class EventEngine extends BaseDaemonThread {
+
+ @Autowired
+ private WorkflowExecuteRunnableRepository workflowExecuteRunnableRepository;
+
+ @Autowired
+ private EventFirer eventFirer;
+
+ private final Set<Integer> firingWorkflowInstanceIds = ConcurrentHashMap.newKeySet();
+
+ public EventEngine() {
+ super("EventEngine");
+ }
+
+ @Override
+ public synchronized void start() {
+ super.start();
+ log.info(getClass().getName() + " started");
+ }
+
+ @Override
+ public void run() {
+ for (;;) {
+ try {
+ StopWatch stopWatch = StopWatch.createStarted();
+ fireAllActiveEvents();
+ stopWatch.stop();
+ log.info("Fire all active events cost: {} ms", stopWatch.getTime());
+ this.wait(5_000);
+ } catch (Throwable throwable) {
+ log.error("Fire active event error", throwable);
+ ThreadUtils.sleep(3_000);
+ }
+ }
+ }
+
+ public void fireAllActiveEvents() {
+ Collection<IWorkflowExecutionRunnable> workflowExecutionRunnableCollection =
+ workflowExecuteRunnableRepository.getActiveWorkflowExecutionRunnable();
+ for (IWorkflowExecutionRunnable workflowExecutionRunnable : workflowExecutionRunnableCollection) {
+ IWorkflowExecutionContext workflowExecutionContext =
+ workflowExecutionRunnable.getWorkflowExecutionContext();
+ final Integer workflowInstanceId = workflowExecutionContext.getWorkflowInstanceId();
+ final String workflowInstanceName = workflowExecutionContext.getWorkflowInstanceName();
+ try {
+ LogUtils.setWorkflowInstanceIdMDC(workflowInstanceId);
+ if (firingWorkflowInstanceIds.contains(workflowInstanceId)) {
+ log.debug("WorkflowExecutionRunnable: {} is already in firing", workflowInstanceName);
+ return;
+ }
+ IEventRepository workflowEventRepository = workflowExecutionRunnable.getEventRepository();
+ firingWorkflowInstanceIds.add(workflowInstanceId);
+ eventFirer.fireActiveEvents(workflowEventRepository)
+ .whenComplete((fireCount, ex) -> {
+ firingWorkflowInstanceIds.remove(workflowInstanceId);
+ if (ex != null) {
+ log.error("Fire event for WorkflowExecutionRunnable: {} error", workflowInstanceName,
+ ex);
+ } else {
+ if (fireCount > 0) {
+ log.info("Fire {} events for WorkflowExecutionRunnable: {} success", fireCount,
+ workflowInstanceName);
+ }
+ }
+ });
+ } finally {
+ LogUtils.removeWorkflowInstanceIdMDC();
+ }
+ }
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/EventFirer.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/EventFirer.java
new file mode 100644
index 0000000000..fbbc683097
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/EventFirer.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.events;
+
+import org.apache.dolphinscheduler.common.thread.ThreadUtils;
+import org.apache.dolphinscheduler.server.master.config.MasterConfig;
+import org.apache.dolphinscheduler.server.master.utils.ExceptionUtils;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class EventFirer implements IEventFirer {
+
+ private final IEventOperatorManager<IEvent> eventOperatorManager;
+
+ private final ThreadPoolExecutor eventFireThreadPool;
+
+ public EventFirer(IEventOperatorManager<IEvent> eventOperatorManager, MasterConfig masterConfig) {
+ this.eventOperatorManager = eventOperatorManager;
+ this.eventFireThreadPool =
+ ThreadUtils.newDaemonFixedThreadExecutor("EventFireThreadPool", masterConfig.getExecThreads());
+ }
+
+ @Override
+ public CompletableFuture<Integer> fireActiveEvents(IEventRepository eventRepository) {
+ if (eventRepository.getEventSize() == 0) {
+ return CompletableFuture.completedFuture(0);
+ }
+ return CompletableFuture.supplyAsync(() -> {
+ int fireCount = 0;
+ for (;;) {
+ IEvent event = eventRepository.poolEvent();
+ if (event == null) {
+ break;
+ }
+
+ if (event instanceof IAsyncEvent) {
+ fireAsyncEvent(event);
+ fireCount++;
+ continue;
+ }
+ try {
+ fireSyncEvent(event);
+ fireCount++;
+ } catch (Exception ex) {
+ if (ExceptionUtils.isDatabaseConnectedFailedException(ex)) {
+ // If the event is failed due to cannot connect to DB, we should retry it
+ eventRepository.storeEventToHead(event);
+ }
+ throw ex;
+ }
+ }
+ return fireCount;
+ }, eventFireThreadPool);
+ }
+
+ private void fireAsyncEvent(IEvent event) {
+ CompletableFuture.runAsync(() -> {
+ log.info("Begin fire IAsyncEvent: {}", event);
+ eventOperatorManager.getEventOperator(event).handleEvent(event);
+ log.info("Success fire IAsyncEvent: {}", event);
+ }, eventFireThreadPool).exceptionally(ex -> {
+ log.error("Failed to fire IAsyncEvent: {}", event, ex);
+ return null;
+ });
+ }
+
+ private void fireSyncEvent(IEvent event) {
+ log.info("Begin fire SyncEvent: {}", event);
+ eventOperatorManager.getEventOperator(event).handleEvent(event);
+ log.info("Success fire SyncEvent: {}", event);
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/EventOperatorManager.java
similarity index 65%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/EventOperatorManager.java
index ac37c94438..7a7b52d6c6 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/EventOperatorManager.java
@@ -15,12 +15,22 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.extern.slf4j.Slf4j;
- public TaskExecutionContextCreateException(String message) {
- super(message);
+import org.springframework.stereotype.Component;
+
+/**
+ * The event operator manager interface used to get {@link ITaskEventOperator}.
+ */
+@Slf4j
+@Component
+public class EventOperatorManager implements IEventOperatorManager<IEvent> {
+
+ @Override
+ public IEventOperator<IEvent> getEventOperator(IEvent event) {
+ return null;
}
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IAsyncEvent.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IAsyncEvent.java
index ac37c94438..0d0395de6e 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IAsyncEvent.java
@@ -15,12 +15,10 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
-
-public class TaskExecutionContextCreateException extends MasterException {
-
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+package org.apache.dolphinscheduler.server.master.events;
+/**
+ * Mark the event as AsyncEvent, if the event is marked as AsyncEvent, the event will be handled asynchronously and we don't .
+ */
+public interface IAsyncEvent {
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IDelayEvent.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IDelayEvent.java
index ac37c94438..c86ea4744f 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IDelayEvent.java
@@ -15,12 +15,12 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+public interface IDelayEvent {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ long getEventCreateTime();
+
+ long getDelayTime();
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IEvent.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IEvent.java
index ac37c94438..0535bbe2c7 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IEvent.java
@@ -15,12 +15,8 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
-
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+public interface IEvent {
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IEventFirer.java
similarity index 66%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IEventFirer.java
index ac37c94438..f33db8ed6a 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IEventFirer.java
@@ -15,12 +15,21 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+import java.util.concurrent.CompletableFuture;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+/**
+ * The event firer interface used to fire event.
+ *
+ */
+public interface IEventFirer {
+
+ /**
+ * Fire all active events in the event repository
+ *
+ * @return the count of fired success events
+ */
+ CompletableFuture<Integer> fireActiveEvents(IEventRepository eventRepository);
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IEventOperator.java
similarity index 75%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IEventOperator.java
index ac37c94438..23694a1ccb 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IEventOperator.java
@@ -15,12 +15,18 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+/**
+ * The event operator interface used to handle event.
+ */
+public interface IEventOperator<E> {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ /**
+ * Handle the given event
+ *
+ * @param event event
+ */
+ void handleEvent(E event);
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IEventOperatorManager.java
similarity index 67%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IEventOperatorManager.java
index ac37c94438..7fb2b63d8a 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IEventOperatorManager.java
@@ -15,12 +15,19 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+/**
+ * The event operator manager interface used to get event operator.
+ */
+public interface IEventOperatorManager<E> {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ /**
+ * Get the {@link IEventOperator} for the given event.
+ *
+ * @param event event
+ * @return event operator for the given event
+ */
+ IEventOperator<E> getEventOperator(E event);
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IEventRepository.java
similarity index 70%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IEventRepository.java
index ac37c94438..20e5081124 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IEventRepository.java
@@ -15,12 +15,23 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+import java.util.List;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+/**
+ * The event repository interface used to store event.
+ */
+public interface IEventRepository {
+
+ void storeEventToTail(IEvent event);
+
+ void storeEventToHead(IEvent event);
+
+ IEvent poolEvent();
+
+ int getEventSize();
+
+ List<IEvent> getAllEvent();
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/ISyncEvent.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/ISyncEvent.java
index ac37c94438..5a385cc034 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/ISyncEvent.java
@@ -15,12 +15,7 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
-
-public class TaskExecutionContextCreateException extends MasterException {
-
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+package org.apache.dolphinscheduler.server.master.events;
+public interface ISyncEvent {
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/ITaskEvent.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/ITaskEvent.java
index ac37c94438..5d105df288 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/ITaskEvent.java
@@ -15,12 +15,12 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+public interface ITaskEvent extends IEvent {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ Integer getWorkflowInstanceId();
+
+ Integer getTaskInstanceId();
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/ITaskEventOperator.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/ITaskEventOperator.java
index ac37c94438..1aa1c28299 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/ITaskEventOperator.java
@@ -15,12 +15,8 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
-
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+public interface ITaskEventOperator<E extends ITaskEvent> extends IEventOperator<E> {
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IWorkflowEvent.java
similarity index 73%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IWorkflowEvent.java
index ac37c94438..7b5ae1cd66 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IWorkflowEvent.java
@@ -15,12 +15,15 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+public interface IWorkflowEvent extends IEvent {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ /**
+ * The id of WorkflowInstance which the event is related to
+ *
+ * @return workflowInstanceId, shouldn't be null
+ */
+ Integer getWorkflowInstanceId();
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IWorkflowEventOperator.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IWorkflowEventOperator.java
index ac37c94438..c601cc27d3 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/IWorkflowEventOperator.java
@@ -15,12 +15,9 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
-
-public class TaskExecutionContextCreateException extends MasterException {
-
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+package org.apache.dolphinscheduler.server.master.events;
+public interface IWorkflowEventOperator<E extends IWorkflowEvent>
+ extends
+ IEventOperator<E> {
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/MemoryEventRepository.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/MemoryEventRepository.java
new file mode 100644
index 0000000000..376b2e4597
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/MemoryEventRepository.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.events;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.LinkedBlockingDeque;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class MemoryEventRepository implements IEventRepository {
+
+ protected final LinkedBlockingDeque<IEvent> eventQueue;
+
+ public MemoryEventRepository() {
+ this.eventQueue = new LinkedBlockingDeque<>();
+ }
+
+ @Override
+ public void storeEventToTail(IEvent event) {
+ log.info("Store event to tail: {}", event);
+ eventQueue.offerLast(event);
+ }
+
+ @Override
+ public void storeEventToHead(IEvent event) {
+ eventQueue.offerFirst(event);
+ }
+
+ @Override
+ public IEvent poolEvent() {
+ return eventQueue.poll();
+ }
+
+ @Override
+ public int getEventSize() {
+ return eventQueue.size();
+ }
+
+ public List<IEvent> getAllEvent() {
+ return new ArrayList<>(eventQueue);
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskLogSendToRemoteEvent.java
similarity index 65%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskLogSendToRemoteEvent.java
index ac37c94438..5e42a40bd6 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskLogSendToRemoteEvent.java
@@ -15,12 +15,22 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TaskLogSendToRemoteEvent implements ITaskEvent {
+ private Integer workflowInstanceId;
+ private Integer taskInstanceId;
+
+ private String taskType;
+ private String logPath;
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskLogSendToRemoteEventOperator.java
similarity index 51%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskLogSendToRemoteEventOperator.java
index ac37c94438..c75f1fcba5 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskLogSendToRemoteEventOperator.java
@@ -15,12 +15,24 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.common.log.remote.RemoteLogUtils;
+import org.apache.dolphinscheduler.server.master.utils.TaskUtils;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.stereotype.Component;
+@Slf4j
+@Component
+public class TaskLogSendToRemoteEventOperator implements ITaskEventOperator<TaskLogSendToRemoteEvent> {
+
+ @Override
+ public void handleEvent(TaskLogSendToRemoteEvent event) {
+ if (RemoteLogUtils.isRemoteLoggingEnable() && TaskUtils.isMasterTask(event.getTaskType())) {
+ RemoteLogUtils.sendRemoteLog(event.getLogPath());
+ log.info("Master sends task log {} to remote storage asynchronously.", event.getLogPath());
+ }
+ }
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskOperationEvent.java
similarity index 50%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskOperationEvent.java
index ac37c94438..165ea88053 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskOperationEvent.java
@@ -15,12 +15,32 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.server.master.dag.TaskExecutionRunnable;
- public TaskExecutionContextCreateException(String message) {
- super(message);
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TaskOperationEvent implements ITaskEvent, ISyncEvent {
+
+ private TaskExecutionRunnable taskExecutionRunnable;
+
+ private TaskOperationType taskOperationType;
+
+ @Override
+ public Integer getWorkflowInstanceId() {
+ return taskExecutionRunnable.getTaskExecutionContext().getTaskInstance().getProcessInstanceId();
}
+ @Override
+ public Integer getTaskInstanceId() {
+ return taskExecutionRunnable.getTaskExecutionContext().getTaskInstance().getId();
+ }
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskOperationEventOperator.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskOperationEventOperator.java
new file mode 100644
index 0000000000..355d28085b
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskOperationEventOperator.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.events;
+
+import org.apache.dolphinscheduler.server.master.dag.TaskExecutionRunnable;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class TaskOperationEventOperator implements ITaskEventOperator<TaskOperationEvent> {
+
+ @Override
+ public void handleEvent(TaskOperationEvent event) {
+ TaskExecutionRunnable taskExecutionRunnable = event.getTaskExecutionRunnable();
+ switch (event.getTaskOperationType()) {
+ case RUN:
+ taskExecutionRunnable.dispatch();
+ break;
+ case KILL:
+ taskExecutionRunnable.kill();
+ break;
+ case PAUSE:
+ taskExecutionRunnable.pause();
+ break;
+ default:
+ log.error("Unknown TaskOperationType for event: {}", event);
+ }
+ }
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskOperationType.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskOperationType.java
index ac37c94438..ae72a03b01 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskOperationType.java
@@ -15,12 +15,15 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+public enum TaskOperationType {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ FAILOVER,
+ RUN,
+ RETRY,
+ KILL,
+ PAUSE,
+ ;
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskSuccessEvent.java
similarity index 71%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskSuccessEvent.java
index ac37c94438..a84d89069a 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskSuccessEvent.java
@@ -15,12 +15,19 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class TaskSuccessEvent implements ITaskEvent {
+
+ private Integer workflowInstanceId;
+
+ private Integer taskInstanceId;
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskSuccessEventOperator.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskSuccessEventOperator.java
new file mode 100644
index 0000000000..8ed9c2033b
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/TaskSuccessEventOperator.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.events;
+
+import org.apache.dolphinscheduler.server.master.dag.IWorkflowExecutionRunnable;
+import org.apache.dolphinscheduler.server.master.dag.WorkflowExecuteRunnableRepository;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class TaskSuccessEventOperator implements ITaskEventOperator<TaskSuccessEvent> {
+
+ @Autowired
+ private WorkflowExecuteRunnableRepository workflowExecuteRunnableRepository;
+
+ @Override
+ public void handleEvent(TaskSuccessEvent event) {
+ Integer workflowInstanceId = event.getWorkflowInstanceId();
+ Integer taskInstanceId = event.getTaskInstanceId();
+ IWorkflowExecutionRunnable workflowExecutionRunnable =
+ workflowExecuteRunnableRepository.getWorkflowExecutionRunnableById(workflowInstanceId);
+ if (workflowExecutionRunnable == null) {
+ log.error("Cannot find the WorkflowExecutionRunnable, the event: {} will be dropped", event);
+ return;
+ }
+
+ }
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowFailedEvent.java
similarity index 68%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowFailedEvent.java
index ac37c94438..f07067c261 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowFailedEvent.java
@@ -15,12 +15,21 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WorkflowFailedEvent implements IWorkflowEvent, ISyncEvent {
+
+ private Integer workflowInstanceId;
+
+ private String failedReason;
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowFailedEventOperator.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowFailedEventOperator.java
new file mode 100644
index 0000000000..b7e562b6f7
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowFailedEventOperator.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.events;
+
+import org.apache.dolphinscheduler.common.enums.WorkflowExecutionStatus;
+import org.apache.dolphinscheduler.dao.entity.ProcessInstance;
+import org.apache.dolphinscheduler.dao.repository.ProcessInstanceDao;
+import org.apache.dolphinscheduler.server.master.dag.IWorkflowExecutionRunnable;
+import org.apache.dolphinscheduler.server.master.dag.WorkflowExecuteRunnableRepository;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class WorkflowFailedEventOperator
+ implements
+ IWorkflowEventOperator<WorkflowFailedEvent> {
+
+ @Autowired
+ private WorkflowExecuteRunnableRepository workflowExecuteRunnableRepository;
+
+ @Autowired
+ private ProcessInstanceDao processInstanceDao;
+
+ @Override
+ public void handleEvent(WorkflowFailedEvent event) {
+ Integer workflowInstanceId = event.getWorkflowInstanceId();
+ IWorkflowExecutionRunnable workflowExecutionRunnable =
+ workflowExecuteRunnableRepository.getWorkflowExecutionRunnableById(workflowInstanceId);
+
+ ProcessInstance workflowInstance =
+ workflowExecutionRunnable.getWorkflowExecutionContext().getWorkflowInstance();
+ workflowInstance.setState(WorkflowExecutionStatus.FAILURE);
+ processInstanceDao.updateById(workflowInstance);
+ log.info("Handle WorkflowExecutionRunnableFailedEvent success, set workflowInstance status to {}",
+ workflowInstance.getState());
+ workflowExecutionRunnable.storeEventToTail(new WorkflowFinalizeEvent(workflowInstanceId));
+ }
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowFinalizeEvent.java
similarity index 70%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowFinalizeEvent.java
index ac37c94438..454b755c42 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowFinalizeEvent.java
@@ -15,12 +15,18 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class WorkflowFinalizeEvent implements IWorkflowEvent, ISyncEvent {
+ private Integer workflowInstanceId;
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowFinalizeEventOperator.java
similarity index 51%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowFinalizeEventOperator.java
index ac37c94438..aeab8ae30c 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowFinalizeEventOperator.java
@@ -15,12 +15,28 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.server.master.dag.WorkflowExecuteRunnableRepository;
- public TaskExecutionContextCreateException(String message) {
- super(message);
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class WorkflowFinalizeEventOperator
+ implements
+ IWorkflowEventOperator<WorkflowFinalizeEvent> {
+
+ @Autowired
+ private WorkflowExecuteRunnableRepository workflowExecuteRunnableRepository;
+
+ @Override
+ public void handleEvent(WorkflowFinalizeEvent event) {
+ Integer workflowInstanceId = event.getWorkflowInstanceId();
+ workflowExecuteRunnableRepository.removeWorkflowExecutionRunnable(workflowInstanceId);
}
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowFinishEvent.java
similarity index 63%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowFinishEvent.java
index ac37c94438..b58db0cc53 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowFinishEvent.java
@@ -15,12 +15,23 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.common.enums.WorkflowExecutionStatus;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WorkflowFinishEvent implements IWorkflowEvent, ISyncEvent {
+
+ private Integer workflowInstanceId;
+
+ private WorkflowExecutionStatus workflowExecutionStatus;
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowOperationEvent.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowOperationEvent.java
new file mode 100644
index 0000000000..6450067f60
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowOperationEvent.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.events;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+
+@Data
+@Builder
+@AllArgsConstructor
+public class WorkflowOperationEvent implements IWorkflowEvent, ISyncEvent {
+
+ private Integer workflowInstanceId;
+ private WorkflowOperationType workflowOperationType;
+
+ public static WorkflowOperationEvent of(Integer workflowInstanceId, WorkflowOperationType workflowOperationType) {
+ return WorkflowOperationEvent.builder()
+ .workflowInstanceId(workflowInstanceId)
+ .workflowOperationType(workflowOperationType)
+ .build();
+ }
+
+ public static WorkflowOperationEvent triggerEvent(Integer workflowInstanceId) {
+ return of(workflowInstanceId, WorkflowOperationType.TRIGGER);
+ }
+
+ public static WorkflowOperationEvent pauseEvent(Integer workflowInstanceId) {
+ return of(workflowInstanceId, WorkflowOperationType.PAUSE);
+ }
+
+ public static WorkflowOperationEvent killEvent(Integer workflowInstanceId) {
+ return of(workflowInstanceId, WorkflowOperationType.KILL);
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowOperationEventOperator.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowOperationEventOperator.java
new file mode 100644
index 0000000000..2c8159f88f
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowOperationEventOperator.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.events;
+
+import org.apache.dolphinscheduler.server.master.dag.IWorkflowExecutionContext;
+import org.apache.dolphinscheduler.server.master.dag.IWorkflowExecutionRunnable;
+import org.apache.dolphinscheduler.server.master.dag.WorkflowExecuteRunnableRepository;
+import org.apache.dolphinscheduler.server.master.utils.ExceptionUtils;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class WorkflowOperationEventOperator implements IWorkflowEventOperator<WorkflowOperationEvent> {
+
+ @Autowired
+ private WorkflowExecuteRunnableRepository workflowExecuteRunnableRepository;
+
+ @Override
+ public void handleEvent(WorkflowOperationEvent event) {
+ IWorkflowExecutionRunnable workflowExecutionRunnable =
+ workflowExecuteRunnableRepository.getWorkflowExecutionRunnableById(event.getWorkflowInstanceId());
+ if (workflowExecutionRunnable == null) {
+ log.warn(
+ "Handle workflowExecutionRunnableKillOperationEvent: {} failed: WorkflowExecutionRunnable not found",
+ event);
+ return;
+ }
+ switch (event.getWorkflowOperationType()) {
+ case TRIGGER:
+ triggerWorkflow(workflowExecutionRunnable);
+ break;
+ case PAUSE:
+ pauseWorkflow(workflowExecutionRunnable);
+ break;
+ case KILL:
+ killWorkflow(workflowExecutionRunnable);
+ break;
+ default:
+ log.error("Unknown operationType for event: {}", event);
+ }
+ }
+
+ private void triggerWorkflow(IWorkflowExecutionRunnable workflowExecutionRunnable) {
+ try {
+ workflowExecutionRunnable.start();
+ } catch (Throwable exception) {
+ if (ExceptionUtils.isDatabaseConnectedFailedException(exception)) {
+ throw exception;
+ }
+ IWorkflowExecutionContext workflowExecutionContext =
+ workflowExecutionRunnable.getWorkflowExecutionContext();
+ log.error("Trigger workflow: {} failed", workflowExecutionContext.getWorkflowInstanceName(), exception);
+ WorkflowFailedEvent workflowExecutionRunnableFailedEvent = WorkflowFailedEvent.builder()
+ .workflowInstanceId(workflowExecutionContext.getWorkflowInstanceId())
+ .failedReason(exception.getMessage())
+ .build();
+ workflowExecutionRunnable.storeEventToTail(workflowExecutionRunnableFailedEvent);
+ }
+ }
+
+ private void pauseWorkflow(IWorkflowExecutionRunnable workflowExecutionRunnable) {
+ workflowExecutionRunnable.pause();
+ }
+
+ private void killWorkflow(IWorkflowExecutionRunnable workflowExecutionRunnable) {
+ workflowExecutionRunnable.kill();
+ }
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowOperationType.java
similarity index 68%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowOperationType.java
index ac37c94438..24abbbc855 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowOperationType.java
@@ -15,12 +15,22 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+public enum WorkflowOperationType {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ /**
+ * Trigger the workflow instance.
+ */
+ TRIGGER,
+ /**
+ * Pause the workflow instance, it will pause the running task instances.
+ */
+ PAUSE,
+ /**
+ * Kill the workflow instance, it will kill the running task instances.
+ */
+ KILL,
+ ;
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowTimeoutEvent.java
similarity index 70%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowTimeoutEvent.java
index ac37c94438..b075d194d7 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowTimeoutEvent.java
@@ -15,12 +15,19 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WorkflowTimeoutEvent implements IWorkflowEvent, IAsyncEvent {
+
+ private Integer workflowInstanceId;
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowTimeoutEventOperator.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowTimeoutEventOperator.java
new file mode 100644
index 0000000000..ebb43e3359
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowTimeoutEventOperator.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.events;
+
+import org.apache.dolphinscheduler.dao.entity.ProcessInstance;
+import org.apache.dolphinscheduler.dao.entity.ProjectUser;
+import org.apache.dolphinscheduler.server.master.dag.IWorkflowExecutionRunnable;
+import org.apache.dolphinscheduler.server.master.dag.WorkflowExecuteRunnableRepository;
+import org.apache.dolphinscheduler.service.alert.ProcessAlertManager;
+import org.apache.dolphinscheduler.service.process.ProcessService;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class WorkflowTimeoutEventOperator
+ implements
+ IEventOperator<WorkflowTimeoutEvent> {
+
+ @Autowired
+ private WorkflowExecuteRunnableRepository workflowExecuteRunnableRepository;
+
+ @Autowired
+ private ProcessService processService;
+
+ @Autowired
+ private ProcessAlertManager processAlertManager;
+
+ @Override
+ public void handleEvent(WorkflowTimeoutEvent event) {
+ IWorkflowExecutionRunnable workflowExecutionRunnable =
+ workflowExecuteRunnableRepository.getWorkflowExecutionRunnableById(event.getWorkflowInstanceId());
+ if (workflowExecutionRunnable == null) {
+ log.warn("Cannot find the workflow instance by id: {}", event.getWorkflowInstanceId());
+ return;
+ }
+ // we only support timeout warning for now
+ ProcessInstance workflowInstance =
+ workflowExecutionRunnable.getWorkflowExecutionContext().getWorkflowInstance();
+ ProjectUser projectUser = processService.queryProjectWithUserByProcessInstanceId(workflowInstance.getId());
+ processAlertManager.sendProcessTimeoutAlert(workflowInstance, projectUser);
+ }
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowTriggerNextTaskEvent.java
similarity index 62%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowTriggerNextTaskEvent.java
index ac37c94438..3dfdb9e239 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowTriggerNextTaskEvent.java
@@ -15,12 +15,24 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WorkflowTriggerNextTaskEvent implements IWorkflowEvent, ISyncEvent {
+
+ private Integer workflowInstanceId;
+
+ /**
+ * The task name of the parent task, if it is the root task, the value is null
+ */
+ private String parentTaskNodeName;
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowTriggerNextTaskEventOperator.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowTriggerNextTaskEventOperator.java
new file mode 100644
index 0000000000..d294b84d58
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowTriggerNextTaskEventOperator.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.events;
+
+import org.apache.dolphinscheduler.server.master.dag.IWorkflowExecutionRunnable;
+import org.apache.dolphinscheduler.server.master.dag.WorkflowExecuteRunnableRepository;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class WorkflowTriggerNextTaskEventOperator
+ implements
+ IWorkflowEventOperator<WorkflowTriggerNextTaskEvent> {
+
+ @Autowired
+ private WorkflowExecuteRunnableRepository workflowExecuteRunnableRepository;
+
+ @Override
+ public void handleEvent(WorkflowTriggerNextTaskEvent event) {
+ IWorkflowExecutionRunnable workflowExecutionRunnable =
+ workflowExecuteRunnableRepository.getWorkflowExecutionRunnableById(event.getWorkflowInstanceId());
+ workflowExecutionRunnable.getDagEngine().triggerNextTasks(event.getParentTaskNodeName());
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowTriggeredEvent.java
similarity index 70%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowTriggeredEvent.java
index ac37c94438..b07434dc29 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowTriggeredEvent.java
@@ -15,12 +15,19 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.events;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WorkflowTriggeredEvent implements IWorkflowEvent, IAsyncEvent {
+
+ private Integer workflowInstanceId;
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowTriggeredEventOperator.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowTriggeredEventOperator.java
new file mode 100644
index 0000000000..e49b1ae70e
--- /dev/null
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/events/WorkflowTriggeredEventOperator.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.events;
+
+import org.apache.dolphinscheduler.dao.entity.ProcessInstance;
+import org.apache.dolphinscheduler.dao.entity.ProjectUser;
+import org.apache.dolphinscheduler.server.master.dag.IWorkflowExecutionRunnable;
+import org.apache.dolphinscheduler.server.master.dag.WorkflowExecuteRunnableRepository;
+import org.apache.dolphinscheduler.server.master.metrics.ProcessInstanceMetrics;
+import org.apache.dolphinscheduler.service.alert.ListenerEventAlertManager;
+import org.apache.dolphinscheduler.service.process.ProcessService;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class WorkflowTriggeredEventOperator
+ implements
+ IWorkflowEventOperator<WorkflowTriggeredEvent> {
+
+ @Autowired
+ private WorkflowExecuteRunnableRepository workflowExecuteRunnableRepository;
+
+ @Autowired
+ private ProcessService processService;
+
+ @Autowired
+ private ListenerEventAlertManager listenerEventAlertManager;
+
+ @Override
+ public void handleEvent(WorkflowTriggeredEvent event) {
+ int workflowInstanceId = event.getWorkflowInstanceId();
+ IWorkflowExecutionRunnable workflowExecutionRunnable =
+ workflowExecuteRunnableRepository.getWorkflowExecutionRunnableById(workflowInstanceId);
+ Long workflowDefinitionCode =
+ workflowExecutionRunnable.getWorkflowExecutionContext().getWorkflowInstance()
+ .getProcessDefinitionCode();
+ ProcessInstanceMetrics.incProcessInstanceByStateAndProcessDefinitionCode("submit", "" + workflowDefinitionCode);
+
+ ProcessInstance workflowInstance =
+ workflowExecutionRunnable.getWorkflowExecutionContext().getWorkflowInstance();
+ ProjectUser projectUser = processService.queryProjectWithUserByProcessInstanceId(workflowInstanceId);
+ listenerEventAlertManager.publishProcessStartListenerEvent(workflowInstance, projectUser);
+ }
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecuteRunnableNotFoundException.java
similarity index 67%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecuteRunnableNotFoundException.java
index ac37c94438..70088d4970 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecuteRunnableNotFoundException.java
@@ -17,10 +17,13 @@
package org.apache.dolphinscheduler.server.master.exception;
-public class TaskExecutionContextCreateException extends MasterException {
+public class TaskExecuteRunnableNotFoundException extends RuntimeException {
- public TaskExecutionContextCreateException(String message) {
- super(message);
+ public TaskExecuteRunnableNotFoundException(Integer workflowInstanceId) {
+ super("WorkflowExecuteRunnable not found: [id=" + workflowInstanceId + "]");
}
+ public TaskExecuteRunnableNotFoundException(String workflowInstanceName) {
+ super("WorkflowExecuteRunnable not found: [name=" + workflowInstanceName + "]");
+ }
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/WorkflowExecuteRunnableNotFoundException.java
similarity index 67%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/WorkflowExecuteRunnableNotFoundException.java
index ac37c94438..f00a8d36e9 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/WorkflowExecuteRunnableNotFoundException.java
@@ -17,10 +17,14 @@
package org.apache.dolphinscheduler.server.master.exception;
-public class TaskExecutionContextCreateException extends MasterException {
+public class WorkflowExecuteRunnableNotFoundException extends RuntimeException {
- public TaskExecutionContextCreateException(String message) {
- super(message);
+ public WorkflowExecuteRunnableNotFoundException(Integer workflowInstanceId) {
+ super("WorkflowExecuteRunnable not found: [id=" + workflowInstanceId + "]");
+ }
+
+ public WorkflowExecuteRunnableNotFoundException(String workflowInstanceName) {
+ super("WorkflowExecuteRunnable not found: [name=" + workflowInstanceName + "]");
}
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/DefaultTaskExecuteRunnable.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/DefaultTaskExecuteRunnable.java
index c1b13717bd..a1e60e0a6e 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/DefaultTaskExecuteRunnable.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/DefaultTaskExecuteRunnable.java
@@ -28,8 +28,7 @@ public class DefaultTaskExecuteRunnable extends PriorityDelayTaskExecuteRunnable
private final TaskExecuteRunnableOperatorManager taskExecuteRunnableOperatorManager;
- public DefaultTaskExecuteRunnable(ProcessInstance workflowInstance,
- TaskInstance taskInstance,
+ public DefaultTaskExecuteRunnable(ProcessInstance workflowInstance, TaskInstance taskInstance,
TaskExecutionContext taskExecutionContext,
TaskExecuteRunnableOperatorManager taskExecuteRunnableOperatorManager) {
super(workflowInstance, taskInstance, taskExecutionContext);
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/TaskExecutionContextFactory.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/TaskExecutionContextFactory.java
index ab1806ff67..742c8187d1 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/TaskExecutionContextFactory.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/TaskExecutionContextFactory.java
@@ -60,7 +60,6 @@ import org.apache.dolphinscheduler.plugin.task.api.utils.MapUtils;
import org.apache.dolphinscheduler.plugin.task.spark.SparkParameters;
import org.apache.dolphinscheduler.server.master.builder.TaskExecutionContextBuilder;
import org.apache.dolphinscheduler.server.master.config.MasterConfig;
-import org.apache.dolphinscheduler.server.master.exception.TaskExecutionContextCreateException;
import org.apache.dolphinscheduler.service.expand.CuringParamsService;
import org.apache.dolphinscheduler.service.process.ProcessService;
import org.apache.dolphinscheduler.spi.datasource.BaseConnectionParam;
@@ -102,7 +101,7 @@ public class TaskExecutionContextFactory {
@Autowired
private HikariDataSource hikariDataSource;
- public TaskExecutionContext createTaskExecutionContext(TaskInstance taskInstance) throws TaskExecutionContextCreateException {
+ public TaskExecutionContext createTaskExecutionContext(TaskInstance taskInstance) {
ProcessInstance workflowInstance = taskInstance.getProcessInstance();
ResourceParametersHelper resources =
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/execute/DefaultTaskExecuteRunnableFactory.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/execute/DefaultTaskExecuteRunnableFactory.java
index ab749b5861..6c1a4e8569 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/execute/DefaultTaskExecuteRunnableFactory.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/execute/DefaultTaskExecuteRunnableFactory.java
@@ -19,8 +19,6 @@ package org.apache.dolphinscheduler.server.master.runner.execute;
import org.apache.dolphinscheduler.dao.entity.TaskInstance;
import org.apache.dolphinscheduler.server.master.cache.ProcessInstanceExecCacheManager;
-import org.apache.dolphinscheduler.server.master.exception.TaskExecuteRunnableCreateException;
-import org.apache.dolphinscheduler.server.master.exception.TaskExecutionContextCreateException;
import org.apache.dolphinscheduler.server.master.runner.DefaultTaskExecuteRunnable;
import org.apache.dolphinscheduler.server.master.runner.TaskExecuteRunnableFactory;
import org.apache.dolphinscheduler.server.master.runner.TaskExecutionContextFactory;
@@ -46,17 +44,13 @@ public class DefaultTaskExecuteRunnableFactory implements TaskExecuteRunnableFac
private TaskExecuteRunnableOperatorManager taskExecuteRunnableOperatorManager;
@Override
- public DefaultTaskExecuteRunnable createTaskExecuteRunnable(TaskInstance taskInstance) throws TaskExecuteRunnableCreateException {
+ public DefaultTaskExecuteRunnable createTaskExecuteRunnable(TaskInstance taskInstance) {
WorkflowExecuteRunnable workflowExecuteRunnable =
processInstanceExecCacheManager.getByProcessInstanceId(taskInstance.getProcessInstanceId());
- try {
- return new DefaultTaskExecuteRunnable(
- workflowExecuteRunnable.getWorkflowExecuteContext().getWorkflowInstance(),
- taskInstance,
- taskExecutionContextFactory.createTaskExecutionContext(taskInstance),
- taskExecuteRunnableOperatorManager);
- } catch (TaskExecutionContextCreateException ex) {
- throw new TaskExecuteRunnableCreateException("Create DefaultTaskExecuteRunnable failed", ex);
- }
+ return new DefaultTaskExecuteRunnable(
+ workflowExecuteRunnable.getWorkflowExecuteContext().getWorkflowInstance(),
+ taskInstance,
+ taskExecutionContextFactory.createTaskExecutionContext(taskInstance),
+ taskExecuteRunnableOperatorManager);
}
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/utils/ExceptionUtils.java
similarity index 70%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/utils/ExceptionUtils.java
index ac37c94438..7cb69b23f5 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/utils/ExceptionUtils.java
@@ -15,12 +15,17 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.utils;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.experimental.UtilityClass;
- public TaskExecutionContextCreateException(String message) {
- super(message);
+import org.springframework.dao.DataAccessResourceFailureException;
+
+@UtilityClass
+public class ExceptionUtils {
+
+ public boolean isDatabaseConnectedFailedException(Throwable e) {
+ return e instanceof DataAccessResourceFailureException;
}
}
diff --git a/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/DAGNodeTest.java b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/DAGNodeTest.java
new file mode 100644
index 0000000000..c3346bfc5d
--- /dev/null
+++ b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/DAGNodeTest.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+
+import org.junit.jupiter.api.Test;
+
+import com.google.common.collect.Lists;
+
+class DAGNodeTest {
+
+ @Test
+ void buildDAGNode_EmptyNodeName() {
+ IllegalArgumentException illegalArgumentException = assertThrows(IllegalArgumentException.class,
+ () -> DAGNode.builder()
+ .inDegrees(new ArrayList<>())
+ .outDegrees(new ArrayList<>())
+ .build());
+ assertEquals("nodeName cannot be empty", illegalArgumentException.getMessage());
+ }
+
+ @Test
+ void buildDAGNode_BadInDegree() {
+ IllegalArgumentException illegalArgumentException = assertThrows(IllegalArgumentException.class,
+ () -> DAGNode.builder()
+ .nodeName("A")
+ .inDegrees(Lists.newArrayList(DAGEdge.builder()
+ .fromNodeName(null)
+ .toNodeName("B")
+ .build()))
+ .outDegrees(new ArrayList<>())
+ .build());
+ assertEquals(
+ "The toNodeName of inDegree should be the nodeName of the node: A, inDegree: DAGEdge(fromNodeName=null, toNodeName=B)",
+ illegalArgumentException.getMessage());
+ }
+
+ @Test
+ void buildDAGNode_NiceInDegree() {
+ assertDoesNotThrow(() -> DAGNode.builder()
+ .nodeName("A")
+ .inDegrees(Lists.newArrayList(DAGEdge.builder()
+ .fromNodeName(null)
+ .toNodeName("A")
+ .build()))
+ .outDegrees(new ArrayList<>())
+ .build());
+ }
+
+ @Test
+ void buildDAGNode_BadOutDegree() {
+ IllegalArgumentException illegalArgumentException = assertThrows(IllegalArgumentException.class,
+ () -> DAGNode.builder()
+ .nodeName("A")
+ .inDegrees(new ArrayList<>())
+ .outDegrees(Lists.newArrayList(DAGEdge.builder()
+ .fromNodeName("B")
+ .toNodeName(null)
+ .build()))
+ .build());
+ assertEquals(
+ "The fromNodeName of outDegree should be the nodeName of the node: A, outDegree: DAGEdge(fromNodeName=B, toNodeName=null)",
+ illegalArgumentException.getMessage());
+ }
+
+ @Test
+ void buildDAGNode_NiceOutDegree() {
+ assertDoesNotThrow(() -> DAGNode.builder()
+ .nodeName("A")
+ .inDegrees(new ArrayList<>())
+ .outDegrees(Lists.newArrayList(DAGEdge.builder()
+ .fromNodeName("A")
+ .toNodeName(null)
+ .build()))
+ .build());
+ }
+
+ @Test
+ void buildDAGNode_NotSkip() {
+ DAGNode dagNode = DAGNode.builder()
+ .nodeName("A")
+ .inDegrees(new ArrayList<>())
+ .outDegrees(new ArrayList<>())
+ .build();
+ assertFalse(dagNode.isSkip());
+ }
+
+ @Test
+ void buildDAGNode_Skip() {
+ DAGNode dagNode = DAGNode.builder()
+ .nodeName("A")
+ .skip(true)
+ .inDegrees(new ArrayList<>())
+ .outDegrees(new ArrayList<>())
+ .build();
+ assertTrue(dagNode.isSkip());
+ }
+
+}
diff --git a/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/MockWorkflowExecutionContextFactory.java b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/MockWorkflowExecutionContextFactory.java
new file mode 100644
index 0000000000..b067a455dd
--- /dev/null
+++ b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/MockWorkflowExecutionContextFactory.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import org.apache.dolphinscheduler.common.utils.CodeGenerateUtils;
+import org.apache.dolphinscheduler.dao.entity.ProcessDefinition;
+import org.apache.dolphinscheduler.dao.entity.ProcessInstance;
+import org.apache.dolphinscheduler.dao.entity.ProcessTaskRelationLog;
+import org.apache.dolphinscheduler.dao.entity.TaskDefinitionLog;
+import org.apache.dolphinscheduler.server.master.events.MemoryEventRepository;
+
+import java.util.Collections;
+
+class MockWorkflowExecutionContextFactory {
+
+ public static WorkflowExecutionContext createWorkflowExecutionContext() {
+ long workflowDefinitionCode = CodeGenerateUtils.getInstance().genCode();
+ int workflowDefinitionVersion = 1;
+
+ int workflowInstanceId = 1;
+ String workflowInstanceName = "MockWorkflow" + CodeGenerateUtils.getInstance().genCode();
+
+ ProcessDefinition processDefinition = ProcessDefinition.builder()
+ .id(1)
+ .name("TestWorkflow")
+ .code(workflowDefinitionCode)
+ .version(workflowDefinitionVersion)
+ .build();
+
+ ProcessInstance processInstance = ProcessInstance.builder()
+ .id(workflowInstanceId)
+ .name(workflowInstanceName)
+ .build();
+
+ WorkflowExecutionDAG workflowExecutionDAG = createWorkflowExecutionDAG();
+
+ return WorkflowExecutionContext.builder()
+ .workflowExecutionDAG(workflowExecutionDAG)
+ .eventRepository(new MemoryEventRepository())
+ .beginNodeNames(Collections.emptyList())
+ .workflowDefinition(processDefinition)
+ .workflowInstance(processInstance)
+ .build();
+ }
+
+ private static WorkflowExecutionDAG createWorkflowExecutionDAG() {
+ TaskDefinitionLog taskA = taskNode("A");
+ WorkflowDAG workflowDAG = WorkflowDAGBuilder.newBuilder()
+ .addTaskNode(taskA)
+ .addTaskEdge(edge(null, taskA))
+ .addTaskEdge(edge(taskA, null))
+ .build();
+
+ return WorkflowExecutionDAG.builder()
+ .workflowDAG(workflowDAG)
+ .taskExecutionRunnableRepository(new TaskExecutionRunnableRepository())
+ .build();
+ }
+
+ private static TaskDefinitionLog taskNode(String nodeName) {
+ TaskDefinitionLog taskDefinitionLog = new TaskDefinitionLog();
+ taskDefinitionLog.setCode(CodeGenerateUtils.getInstance().genCode());
+ taskDefinitionLog.setName(nodeName);
+ return taskDefinitionLog;
+ }
+
+ private static ProcessTaskRelationLog edge(TaskDefinitionLog from, TaskDefinitionLog to) {
+ ProcessTaskRelationLog processTaskRelationLog = new ProcessTaskRelationLog();
+ processTaskRelationLog.setPreTaskCode(from == null ? 0 : from.getCode());
+ processTaskRelationLog.setPostTaskCode(to == null ? 0 : to.getCode());
+ return processTaskRelationLog;
+ }
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/MockWorkflowExecutionRunnableFactory.java
similarity index 58%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/MockWorkflowExecutionRunnableFactory.java
index ac37c94438..77745e198b 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/MockWorkflowExecutionRunnableFactory.java
@@ -15,12 +15,17 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+class MockWorkflowExecutionRunnableFactory {
- public TaskExecutionContextCreateException(String message) {
- super(message);
+ public static WorkflowExecutionRunnable createWorkflowExecuteRunnable() {
+ WorkflowExecutionContext workflowExecutionContext =
+ MockWorkflowExecutionContextFactory.createWorkflowExecutionContext();
+ IDAGEngine dagEngine = new DAGEngine(workflowExecutionContext);
+ return WorkflowExecutionRunnable.builder()
+ .workflowExecutionContext(workflowExecutionContext)
+ .dagEngine(dagEngine)
+ .build();
}
-
}
diff --git a/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowDAGAssertion.java b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowDAGAssertion.java
new file mode 100644
index 0000000000..a03ecd9f76
--- /dev/null
+++ b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowDAGAssertion.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.commons.collections4.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class WorkflowDAGAssertion {
+
+ private final IWorkflowDAG workflowDAG;
+
+ private final List<NodeAssertion> nodeAssertions;
+
+ private WorkflowDAGAssertion(IWorkflowDAG workflowDAG) {
+ this.workflowDAG = workflowDAG;
+ this.nodeAssertions = new ArrayList<>();
+ }
+
+ public static WorkflowDAGAssertion workflowDag(IWorkflowDAG workflowDAG) {
+ return new WorkflowDAGAssertion(workflowDAG);
+ }
+
+ public WorkflowDAGAssertion nodeAssertion(NodeAssertion nodeAssertion) {
+ nodeAssertions.add(nodeAssertion);
+ return this;
+ }
+
+ public void doAssertion() {
+ nodeAssertions.forEach(nodeAssertion -> nodeAssertion.doAssertion(workflowDAG));
+ }
+
+ public static class NodeAssertion {
+
+ /**
+ * node name of the assertion
+ */
+ private final String nodeName;
+
+ /**
+ * whether the node exist
+ */
+ private boolean exist;
+
+ /**
+ * whether the node is skipped
+ */
+ private boolean skip;
+
+ /**
+ * whether the node has out degree
+ */
+ private List<String> postNodes;
+
+ /**
+ * whether the node has in degree
+ */
+ private List<String> preNodes;
+
+ private NodeAssertion(String nodeName) {
+ this.nodeName = nodeName;
+ this.postNodes = new ArrayList<>();
+ this.preNodes = new ArrayList<>();
+ }
+
+ public static NodeAssertion node(String nodeName) {
+ return new NodeAssertion(nodeName);
+ }
+
+ public NodeAssertion exist() {
+ this.exist = true;
+ return this;
+ }
+
+ public NodeAssertion skip() {
+ this.skip = true;
+ return this;
+ }
+
+ public NodeAssertion noEdge() {
+ this.postNodes = new ArrayList<>();
+ this.preNodes = new ArrayList<>();
+ return this;
+ }
+
+ public NodeAssertion noInDegree() {
+ this.preNodes = new ArrayList<>();
+ return this;
+ }
+
+ public NodeAssertion inDegrees(List<String> preNodes) {
+ this.preNodes.addAll(preNodes);
+ return this;
+ }
+
+ public NodeAssertion inDegrees(String preNode) {
+ this.preNodes.add(preNode);
+ return this;
+ }
+
+ public NodeAssertion noOutDegree() {
+ this.postNodes = new ArrayList<>();
+ return this;
+ }
+
+ public NodeAssertion outDegrees(List<String> postNodes) {
+ this.postNodes.addAll(postNodes);
+ return this;
+ }
+
+ public NodeAssertion outDegrees(String postNode) {
+ this.postNodes.add(postNode);
+ return this;
+ }
+
+ private void doAssertion(IWorkflowDAG workflowDAG) {
+ if (exist) {
+ // node exist
+ assertNotNull(workflowDAG.getDAGNode(nodeName), "node " + nodeName + " does not exist");
+ } else {
+
+ assertNull(workflowDAG.getDAGNode(nodeName), "node " + nodeName + " exist");
+ }
+
+ if (skip) {
+ assertTrue(workflowDAG.getDAGNode(nodeName).isSkip(), "node " + nodeName + " is not skipped");
+ } else {
+ assertFalse(workflowDAG.getDAGNode(nodeName).isSkip(), "node " + nodeName + " is skipped");
+ }
+
+ if (CollectionUtils.isEmpty(postNodes)) {
+ assertTrue(workflowDAG.getDirectPostNodeNames(nodeName).isEmpty(),
+ "node " + nodeName + " has outDegree " + workflowDAG.getDirectPostNodes(nodeName));
+ } else {
+ postNodes
+ .forEach(postNode -> assertTrue(workflowDAG.getDirectPostNodeNames(nodeName).contains(postNode),
+ "node " + nodeName + " does has outDegree " + postNode));
+ }
+
+ if (CollectionUtils.isEmpty(preNodes)) {
+ assertTrue(workflowDAG.getDirectPreNodeNames(nodeName).isEmpty(),
+ "node " + nodeName + " has inDegree " + workflowDAG.getDirectPreNodeNames(nodeName));
+ } else {
+ preNodes.forEach(preNode -> assertTrue(workflowDAG.getDirectPreNodeNames(nodeName).contains(preNode),
+ "node " + nodeName + " does has inDegree " + preNode));
+ }
+ }
+ }
+
+}
diff --git a/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowDAGBuilderTest.java b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowDAGBuilderTest.java
new file mode 100644
index 0000000000..a4abb8156f
--- /dev/null
+++ b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowDAGBuilderTest.java
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.apache.dolphinscheduler.server.master.dag.WorkflowDAGAssertion.NodeAssertion.node;
+import static org.apache.dolphinscheduler.server.master.dag.WorkflowDAGAssertion.workflowDag;
+
+import org.apache.dolphinscheduler.common.utils.CodeGenerateUtils;
+import org.apache.dolphinscheduler.dao.entity.ProcessTaskRelationLog;
+import org.apache.dolphinscheduler.dao.entity.TaskDefinitionLog;
+
+import org.junit.jupiter.api.Test;
+
+class WorkflowDAGBuilderTest {
+
+ /**
+ * Test DAG with single node:
+ * <pre>
+ * {@code
+ * Node(A)
+ * }
+ * </pre>
+ */
+ @Test
+ void build_SingleTaskNode() {
+ String nodeName = "A";
+ TaskDefinitionLog taskDefinitionLog = taskNode(nodeName);
+ WorkflowDAG workflowDAG = WorkflowDAGBuilder.newBuilder()
+ .addTaskNode(taskDefinitionLog)
+ .build();
+ workflowDag(workflowDAG)
+ .nodeAssertion(node(nodeName).exist().noEdge())
+ .doAssertion();
+ }
+
+ /**
+ * Test DAG with multiple nodes:
+ * <pre>
+ * {@code
+ * Node(A)
+ * Node(B)
+ * Node(C)
+ * }
+ * <pre/>
+ */
+ @Test
+ void build_MULTIPLE_NODE() {
+ String nodeNameA = "A";
+ TaskDefinitionLog taskNodeA = taskNode(nodeNameA);
+ String nodeNameB = "B";
+ TaskDefinitionLog taskNodeB = taskNode(nodeNameB);
+ String nodeNameC = "C";
+ TaskDefinitionLog taskNodeC = taskNode(nodeNameC);
+
+ WorkflowDAG workflowDAG = WorkflowDAGBuilder.newBuilder()
+ .addTaskNode(taskNodeA)
+ .addTaskNode(taskNodeB)
+ .addTaskNode(taskNodeC)
+ .build();
+ workflowDag(workflowDAG)
+ .nodeAssertion(node(nodeNameA).exist().noEdge())
+ .nodeAssertion(node(nodeNameB).exist().noEdge())
+ .nodeAssertion(node(nodeNameC).exist().noEdge())
+ .doAssertion();
+ }
+
+ /**
+ * Test DAG with multiple nodes:
+ * <pre>
+ * {@code
+ * Node(A) -> Node(B1) -> Node(C1) -> Node(D)
+ * -> Node(B2) -> Node(C2) ->
+ * }
+ * <pre/>
+ */
+ @Test
+ void build_DAG() {
+ String nodeNameA = "A";
+ TaskDefinitionLog taskNodeA = taskNode(nodeNameA);
+ String nodeNameB1 = "B1";
+ TaskDefinitionLog taskNodeB1 = taskNode(nodeNameB1);
+ String nodeNameB2 = "B2";
+ TaskDefinitionLog taskNodeB2 = taskNode(nodeNameB2);
+ String nodeNameC1 = "C1";
+ TaskDefinitionLog taskNodeC1 = taskNode(nodeNameC1);
+ String nodeNameC2 = "C2";
+ TaskDefinitionLog taskNodeC2 = taskNode(nodeNameC2);
+ String nodeNameD = "D";
+ TaskDefinitionLog taskNodeD = taskNode(nodeNameD);
+
+ WorkflowDAG workflowDAG = WorkflowDAGBuilder.newBuilder()
+ .addTaskNode(taskNodeA)
+ .addTaskNodes(newArrayList(taskNodeB1, taskNodeB2))
+ .addTaskNodes(newArrayList(taskNodeC1, taskNodeC2))
+ .addTaskNode(taskNodeD)
+ .addTaskEdge(edge(null, taskNodeA))
+ .addTaskEdge(edge(taskNodeA, taskNodeB1))
+ .addTaskEdge(edge(taskNodeA, taskNodeB2))
+ .addTaskEdge(edge(taskNodeB1, taskNodeC1))
+ .addTaskEdge(edge(taskNodeB2, taskNodeC2))
+ .addTaskEdge(edge(taskNodeC1, taskNodeD))
+ .addTaskEdge(edge(taskNodeC2, taskNodeD))
+ .addTaskEdge(edge(taskNodeD, null))
+ .build();
+ workflowDag(workflowDAG)
+ .nodeAssertion(node(nodeNameA)
+ .exist()
+ .noInDegree()
+ .outDegrees(newArrayList(nodeNameB1, nodeNameB2)))
+ .nodeAssertion(node(nodeNameB1)
+ .exist()
+ .inDegrees(nodeNameA)
+ .outDegrees(nodeNameC1))
+ .nodeAssertion(node(nodeNameB2)
+ .exist()
+ .inDegrees(nodeNameA)
+ .outDegrees(nodeNameC2))
+ .nodeAssertion(node(nodeNameC1)
+ .exist()
+ .inDegrees(nodeNameB1)
+ .outDegrees(nodeNameD))
+ .nodeAssertion(node(nodeNameC2)
+ .exist()
+ .inDegrees(nodeNameB2)
+ .outDegrees(nodeNameD))
+ .nodeAssertion(node(nodeNameD)
+ .exist()
+ .inDegrees(newArrayList(nodeNameC1, nodeNameC2))
+ .noOutDegree())
+ .doAssertion();
+ }
+
+ /**
+ * Test DAG with multiple sub dags:
+ * <pre>
+ * {@code
+ * Node(A1) -> Node(B1) -> Node(C1) -> Node(D1)
+ * -> Node(B2) -> Node(C2) ->
+ *
+ * Node(A2) -> Node(B3) -> Node(C3) -> Node(D2)
+ * -> Node(B4) -> Node(C4) ->
+ * }
+ * <pre/>
+ */
+ @Test
+ void build_MULTIPLE_SUB_DAG() {
+ String nodeNameA1 = "A1";
+ TaskDefinitionLog taskNodeA1 = taskNode(nodeNameA1);
+ String nodeNameA2 = "A2";
+ TaskDefinitionLog taskNodeA2 = taskNode(nodeNameA2);
+
+ String nodeNameB1 = "B1";
+ TaskDefinitionLog taskNodeB1 = taskNode(nodeNameB1);
+ String nodeNameB2 = "B2";
+ TaskDefinitionLog taskNodeB2 = taskNode(nodeNameB2);
+ String nodeNameB3 = "B3";
+ TaskDefinitionLog taskNodeB3 = taskNode(nodeNameB3);
+ String nodeNameB4 = "B4";
+ TaskDefinitionLog taskNodeB4 = taskNode(nodeNameB4);
+
+ String nodeNameC1 = "C1";
+ TaskDefinitionLog taskNodeC1 = taskNode(nodeNameC1);
+ String nodeNameC2 = "C2";
+ TaskDefinitionLog taskNodeC2 = taskNode(nodeNameC2);
+ String nodeNameC3 = "C3";
+ TaskDefinitionLog taskNodeC3 = taskNode(nodeNameC3);
+ String nodeNameC4 = "C4";
+ TaskDefinitionLog taskNodeC4 = taskNode(nodeNameC4);
+
+ String nodeNameD1 = "D1";
+ TaskDefinitionLog taskNodeD1 = taskNode(nodeNameD1);
+ String nodeNameD2 = "D2";
+ TaskDefinitionLog taskNodeD2 = taskNode(nodeNameD2);
+
+ WorkflowDAG workflowDAG = WorkflowDAGBuilder.newBuilder()
+ .addTaskNodes(newArrayList(taskNodeA1, taskNodeA2))
+ .addTaskNodes(newArrayList(taskNodeB1, taskNodeB2, taskNodeB3, taskNodeB4))
+ .addTaskNodes(newArrayList(taskNodeC1, taskNodeC2, taskNodeC3, taskNodeC4))
+ .addTaskNodes(newArrayList(taskNodeD1, taskNodeD2))
+ .addTaskEdge(edge(null, taskNodeA1))
+ .addTaskEdge(edge(taskNodeA1, taskNodeB1))
+ .addTaskEdge(edge(taskNodeA1, taskNodeB2))
+ .addTaskEdge(edge(taskNodeB1, taskNodeC1))
+ .addTaskEdge(edge(taskNodeB2, taskNodeC2))
+ .addTaskEdge(edge(taskNodeC1, taskNodeD1))
+ .addTaskEdge(edge(taskNodeC2, taskNodeD1))
+ .addTaskEdge(edge(taskNodeD1, null))
+ .addTaskEdge(edge(null, taskNodeA2))
+ .addTaskEdge(edge(taskNodeA2, taskNodeB3))
+ .addTaskEdge(edge(taskNodeA2, taskNodeB4))
+ .addTaskEdge(edge(taskNodeB3, taskNodeC3))
+ .addTaskEdge(edge(taskNodeB4, taskNodeC4))
+ .addTaskEdge(edge(taskNodeC3, taskNodeD2))
+ .addTaskEdge(edge(taskNodeC4, taskNodeD2))
+ .addTaskEdge(edge(taskNodeD2, null))
+ .build();
+
+ workflowDag(workflowDAG)
+ .nodeAssertion(node(nodeNameA1)
+ .exist()
+ .noInDegree()
+ .outDegrees(newArrayList(nodeNameB1, nodeNameB2)))
+ .nodeAssertion(node(nodeNameB1)
+ .exist()
+ .inDegrees(nodeNameA1)
+ .outDegrees(nodeNameC1))
+ .nodeAssertion(node(nodeNameB2)
+ .exist()
+ .inDegrees(nodeNameA1)
+ .outDegrees(nodeNameC2))
+ .nodeAssertion(node(nodeNameC1)
+ .exist()
+ .inDegrees(nodeNameB1)
+ .outDegrees(nodeNameD1))
+ .nodeAssertion(node(nodeNameC2)
+ .exist()
+ .inDegrees(nodeNameB2)
+ .outDegrees(nodeNameD1))
+ .nodeAssertion(node(nodeNameD1)
+ .exist()
+ .inDegrees(newArrayList(nodeNameC1, nodeNameC2))
+ .noOutDegree())
+ .doAssertion();
+ workflowDag(workflowDAG)
+ .nodeAssertion(node(nodeNameA2)
+ .exist()
+ .noInDegree()
+ .outDegrees(newArrayList(nodeNameB3, nodeNameB4)))
+ .nodeAssertion(node(nodeNameB3)
+ .exist()
+ .inDegrees(nodeNameA2)
+ .outDegrees(nodeNameC3))
+ .nodeAssertion(node(nodeNameB4)
+ .exist()
+ .inDegrees(nodeNameA2)
+ .outDegrees(nodeNameC4))
+ .nodeAssertion(node(nodeNameC3)
+ .exist()
+ .inDegrees(nodeNameB3)
+ .outDegrees(nodeNameD2))
+ .nodeAssertion(node(nodeNameC4)
+ .exist()
+ .inDegrees(nodeNameB4)
+ .outDegrees(nodeNameD2))
+ .nodeAssertion(node(nodeNameD2)
+ .exist()
+ .inDegrees(newArrayList(nodeNameC3, nodeNameC4))
+ .noOutDegree())
+ .doAssertion();
+ }
+
+ private TaskDefinitionLog taskNode(String nodeName) {
+ TaskDefinitionLog taskDefinitionLog = new TaskDefinitionLog();
+ taskDefinitionLog.setCode(CodeGenerateUtils.getInstance().genCode());
+ taskDefinitionLog.setName(nodeName);
+ return taskDefinitionLog;
+ }
+
+ private ProcessTaskRelationLog edge(TaskDefinitionLog from, TaskDefinitionLog to) {
+ ProcessTaskRelationLog processTaskRelationLog = new ProcessTaskRelationLog();
+ processTaskRelationLog.setPreTaskCode(from == null ? 0 : from.getCode());
+ processTaskRelationLog.setPostTaskCode(to == null ? 0 : to.getCode());
+ return processTaskRelationLog;
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowEngineIT.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowEngineIT.java
index ac37c94438..ede8b55a37 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowEngineIT.java
@@ -15,12 +15,8 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.server.master.dag;
-public class TaskExecutionContextCreateException extends MasterException {
-
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+public class WorkflowEngineIT {
}
diff --git a/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowEngineTest.java b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowEngineTest.java
new file mode 100644
index 0000000000..b6e5dc9db5
--- /dev/null
+++ b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowEngineTest.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import static org.apache.dolphinscheduler.server.master.dag.WorkflowExecutionRunnableAssertions.workflowExecutionRunnable;
+import static org.apache.dolphinscheduler.server.master.dag.WorkflowExecutionRunnableRepositoryAssertions.workflowExecutionRunnableRepository;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.apache.dolphinscheduler.server.master.events.WorkflowOperationEvent;
+import org.apache.dolphinscheduler.server.master.exception.WorkflowExecuteRunnableNotFoundException;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class WorkflowEngineTest {
+
+ private WorkflowExecuteRunnableRepository workflowExecuteRunnableRepository;
+ private WorkflowEngine workflowEngine;
+
+ @BeforeEach
+ public void before() {
+ workflowExecuteRunnableRepository = new WorkflowExecuteRunnableRepository();
+ workflowEngine = new WorkflowEngine(workflowExecuteRunnableRepository);
+ }
+
+ @Test
+ void triggerWorkflow() {
+ IWorkflowExecutionRunnable emptyWorkflowExecuteRunnable =
+ MockWorkflowExecutionRunnableFactory.createWorkflowExecuteRunnable();
+ Integer workflowInstanceId = emptyWorkflowExecuteRunnable.getWorkflowExecutionContext().getWorkflowInstanceId();
+
+ workflowEngine.triggerWorkflow(emptyWorkflowExecuteRunnable);
+ workflowExecutionRunnable(emptyWorkflowExecuteRunnable)
+ .existEvent(WorkflowOperationEvent.triggerEvent(workflowInstanceId));
+ }
+
+ @Test
+ void pauseWorkflow_WorkflowNotExist() {
+ WorkflowExecuteRunnableNotFoundException exception =
+ assertThrows(WorkflowExecuteRunnableNotFoundException.class, () -> workflowEngine.pauseWorkflow(1));
+ assertEquals("WorkflowExecuteRunnable not found: [id=1]", exception.getMessage());
+ }
+
+ @Test
+ void pauseWorkflow_WorkflowExist() {
+ IWorkflowExecutionRunnable emptyWorkflowExecuteRunnable =
+ MockWorkflowExecutionRunnableFactory.createWorkflowExecuteRunnable();
+ Integer workflowInstanceId =
+ emptyWorkflowExecuteRunnable.getWorkflowExecutionContext().getWorkflowInstanceId();
+ workflowExecuteRunnableRepository.storeWorkflowExecutionRunnable(emptyWorkflowExecuteRunnable);
+
+ workflowEngine.pauseWorkflow(workflowInstanceId);
+ workflowExecutionRunnable(emptyWorkflowExecuteRunnable)
+ .existEvent(WorkflowOperationEvent.pauseEvent(workflowInstanceId));
+ }
+
+ @Test
+ void killWorkflow_WorkflowNotExist() {
+ WorkflowExecuteRunnableNotFoundException exception =
+ assertThrows(WorkflowExecuteRunnableNotFoundException.class,
+ () -> workflowEngine.killWorkflow(1));
+ assertEquals("WorkflowExecuteRunnable not found: [id=1]", exception.getMessage());
+ }
+
+ @Test
+ void killWorkflow_WorkflowExist() {
+ IWorkflowExecutionRunnable emptyWorkflowExecuteRunnable =
+ MockWorkflowExecutionRunnableFactory.createWorkflowExecuteRunnable();
+ Integer workflowInstanceId =
+ emptyWorkflowExecuteRunnable.getWorkflowExecutionContext().getWorkflowInstanceId();
+ workflowExecuteRunnableRepository.storeWorkflowExecutionRunnable(emptyWorkflowExecuteRunnable);
+
+ workflowEngine.killWorkflow(workflowInstanceId);
+ workflowExecutionRunnable(emptyWorkflowExecuteRunnable)
+ .existEvent(WorkflowOperationEvent.killEvent(workflowInstanceId));
+ }
+
+ @Test
+ void finalizeWorkflow_WorkflowNotExist() {
+ workflowEngine.finalizeWorkflow(1);
+ }
+
+ @Test
+ void finalizeWorkflow_WorkflowExist() {
+ IWorkflowExecutionRunnable emptyWorkflowExecuteRunnable =
+ MockWorkflowExecutionRunnableFactory.createWorkflowExecuteRunnable();
+ Integer workflowInstanceId =
+ emptyWorkflowExecuteRunnable.getWorkflowExecutionContext().getWorkflowInstanceId();
+ workflowExecuteRunnableRepository.storeWorkflowExecutionRunnable(emptyWorkflowExecuteRunnable);
+ workflowExecutionRunnableRepository(workflowExecuteRunnableRepository)
+ .existWorkflowExecutionRunnable(workflowInstanceId);
+
+ workflowEngine.finalizeWorkflow(workflowInstanceId);
+ workflowExecutionRunnableRepository(workflowExecuteRunnableRepository)
+ .notExistWorkflowExecutionRunnable(workflowInstanceId);
+ }
+
+}
diff --git a/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionRunnableAssertions.java b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionRunnableAssertions.java
new file mode 100644
index 0000000000..65cf7ba7cd
--- /dev/null
+++ b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionRunnableAssertions.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import org.apache.dolphinscheduler.server.master.events.IEvent;
+
+import org.opentest4j.AssertionFailedError;
+
+class WorkflowExecutionRunnableAssertions {
+
+ private final IWorkflowExecutionRunnable workflowExecutionRunnable;
+
+ private WorkflowExecutionRunnableAssertions(IWorkflowExecutionRunnable workflowExecutionRunnable) {
+ this.workflowExecutionRunnable = workflowExecutionRunnable;
+ }
+
+ public static WorkflowExecutionRunnableAssertions workflowExecutionRunnable(IWorkflowExecutionRunnable workflowExecutionRunnable) {
+ return new WorkflowExecutionRunnableAssertions(workflowExecutionRunnable);
+ }
+
+ public void existEvent(IEvent event) {
+ if (event == null) {
+ throw new IllegalArgumentException("Event cannot be null");
+ }
+ boolean exist = workflowExecutionRunnable.getEventRepository().getAllEvent()
+ .stream()
+ .anyMatch(event1 -> event1.equals(event1));
+ if (!exist) {
+ throw new AssertionFailedError("The workflowExecuteRunnable doesn't exist event: " + event);
+ }
+ }
+
+}
diff --git a/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionRunnableRepositoryAssertions.java b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionRunnableRepositoryAssertions.java
new file mode 100644
index 0000000000..e979f35cb3
--- /dev/null
+++ b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionRunnableRepositoryAssertions.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+class WorkflowExecutionRunnableRepositoryAssertions {
+
+ private final WorkflowExecuteRunnableRepository workflowExecuteRunnableRepository;
+
+ private WorkflowExecutionRunnableRepositoryAssertions(WorkflowExecuteRunnableRepository workflowExecuteRunnableRepository) {
+ this.workflowExecuteRunnableRepository = workflowExecuteRunnableRepository;
+ }
+
+ public static WorkflowExecutionRunnableRepositoryAssertions workflowExecutionRunnableRepository(WorkflowExecuteRunnableRepository workflowExecuteRunnableRepository) {
+ return new WorkflowExecutionRunnableRepositoryAssertions(workflowExecuteRunnableRepository);
+ }
+
+ public void existWorkflowExecutionRunnable(Integer workflowInstanceId) {
+ assertNotNull(workflowExecuteRunnableRepository.getWorkflowExecutionRunnableById(workflowInstanceId));
+ }
+
+ public void notExistWorkflowExecutionRunnable(Integer workflowInstanceId) {
+ assertNull(workflowExecuteRunnableRepository.getWorkflowExecutionRunnableById(workflowInstanceId));
+ }
+
+}
diff --git a/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionRunnableTest.java b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionRunnableTest.java
new file mode 100644
index 0000000000..69a7f83a50
--- /dev/null
+++ b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/dag/WorkflowExecutionRunnableTest.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.dag;
+
+import static org.apache.dolphinscheduler.server.master.dag.WorkflowExecutionRunnableAssertions.workflowExecutionRunnable;
+
+import org.apache.dolphinscheduler.server.master.events.WorkflowTriggeredEvent;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class WorkflowExecutionRunnableTest {
+
+ private WorkflowExecutionRunnable workflowExecutionRunnable;
+
+ @BeforeEach
+ public void before() {
+ workflowExecutionRunnable = MockWorkflowExecutionRunnableFactory.createWorkflowExecuteRunnable();
+ }
+
+ @Test
+ void start() {
+ workflowExecutionRunnable.start();
+ workflowExecutionRunnable(workflowExecutionRunnable)
+ .existEvent(new WorkflowTriggeredEvent(
+ workflowExecutionRunnable.getWorkflowExecutionContext().getWorkflowInstance().getId()));
+ }
+
+ @Test
+ void pause() {
+ }
+
+ @Test
+ void kill() {
+ }
+}
diff --git a/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/events/WorkflowOperationEventTest.java b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/events/WorkflowOperationEventTest.java
new file mode 100644
index 0000000000..00bea9f601
--- /dev/null
+++ b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/events/WorkflowOperationEventTest.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.server.master.events;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+class WorkflowOperationEventTest {
+
+ @Test
+ void triggerEvent() {
+ WorkflowOperationEvent workflowOperationEvent = WorkflowOperationEvent.triggerEvent(1);
+ assertEquals(1, workflowOperationEvent.getWorkflowInstanceId());
+ assertEquals(WorkflowOperationType.TRIGGER, workflowOperationEvent.getWorkflowOperationType());
+ }
+
+ @Test
+ void pauseEvent() {
+ WorkflowOperationEvent workflowOperationEvent = WorkflowOperationEvent.pauseEvent(1);
+ assertEquals(1, workflowOperationEvent.getWorkflowInstanceId());
+ assertEquals(WorkflowOperationType.PAUSE, workflowOperationEvent.getWorkflowOperationType());
+ }
+
+ @Test
+ void killEvent() {
+ WorkflowOperationEvent workflowOperationEvent = WorkflowOperationEvent.killEvent(1);
+ assertEquals(1, workflowOperationEvent.getWorkflowInstanceId());
+ assertEquals(WorkflowOperationType.KILL, workflowOperationEvent.getWorkflowOperationType());
+ }
+}
diff --git a/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/utils/ExceptionUtilsTest.java b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/utils/ExceptionUtilsTest.java
new file mode 100644
index 0000000000..440f33b474
--- /dev/null
+++ b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/utils/ExceptionUtilsTest.java
@@ -0,0 +1,18 @@
+package org.apache.dolphinscheduler.server.master.utils;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.dao.DataAccessResourceFailureException;
+
+class ExceptionUtilsTest {
+
+ @Test
+ void isDatabaseConnectedFailedException() {
+ // todo: Directly connect to database
+ assertTrue(ExceptionUtils.isDatabaseConnectedFailedException(
+ new DataAccessResourceFailureException("Database connection failed")));
+ assertFalse(ExceptionUtils.isDatabaseConnectedFailedException(new RuntimeException("runtime exception")));
+ }
+}
diff --git a/dolphinscheduler-workflow-engine/README.md b/dolphinscheduler-workflow-engine/README.md
new file mode 100644
index 0000000000..6a14acf775
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/README.md
@@ -0,0 +1,2 @@
+# Introduction
+
\ No newline at end of file
diff --git a/dolphinscheduler-workflow-engine/pom.xml b/dolphinscheduler-workflow-engine/pom.xml
new file mode 100644
index 0000000000..40a360e7c8
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.dolphinscheduler</groupId>
+ <artifactId>dolphinscheduler</artifactId>
+ <version>dev-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>dolphinscheduler-workflow-engine</artifactId>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.dolphinscheduler</groupId>
+ <artifactId>dolphinscheduler-bom</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.dolphinscheduler</groupId>
+ <artifactId>dolphinscheduler-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-tx</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/DAG.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/DAG.java
new file mode 100644
index 0000000000..63e6370887
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/DAG.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.dag;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * The Directed Acyclic Graph class.
+ * <p>
+ * The DAG is a directed graph, which contains the nodes and the edges, the nodeName is the unique identifier of the node.
+ * The nodes are the tasks, the edges are the dependencies between the tasks.
+ * The DAG is acyclic, which means there is no cycle in the graph.
+ * The DAG is a directed graph, which means the edges have direction.
+ *
+ */
+public interface DAG {
+
+ /**
+ * Get the direct post node of given dagNode, if the dagNode is null, return the nodes which doesn't have inDegrees.
+ * e.g. The DAG is:
+ * <pre>
+ * {@code
+ * 1 -> 2 -> 3
+ * 4 -> 5
+ * 6
+ * }
+ * </pre>
+ * <li> The post node of 1 is 2.
+ * <li> The post node of 3 is empty.
+ * <li> The post node of null is 1,4,6.
+ *
+ * @param dagNode the node of the DAG, can be null.
+ * @return post node list, sort by priority.
+ */
+ List<DAGNode> getDirectPostNodes(DAGNode dagNode);
+
+ /**
+ * Same with {@link #getDirectPostNodes(DAGNode)}.
+ * <p>
+ * If the dagNodeName is null, return the nodes which doesn't have inDegrees. Otherwise, return the post nodes of
+ * the given dagNodeName. If the dagNodeName is not null and cannot find the node in DAG, throw IllegalArgumentException.
+ *
+ * @param dagNodeName task name, can be null.
+ * @return post task name list, sort by priority.
+ * @throws IllegalArgumentException if the dagNodeName is not null and cannot find the node in DAG.
+ */
+ default List<DAGNode> getDirectPostNodes(String dagNodeName) {
+ DAGNode dagNode = getDAGNode(dagNodeName);
+ if (dagNodeName != null && dagNode == null) {
+ throw new IllegalArgumentException("Cannot find the Node: " + dagNodeName + " in DAG");
+ }
+ return getDirectPostNodes(dagNode);
+ }
+
+ /**
+ * Same with {@link #getDirectPostNodes(String)}. Return the post node names.
+ *
+ * @param dagNodeName task name, can be null.
+ * @return post task name list, sort by priority.
+ * @throws IllegalArgumentException if the dagNodeName is not null and cannot find the node in DAG.
+ */
+ default List<String> getDirectPostNodeNames(String dagNodeName) {
+ DAGNode dagNode = getDAGNode(dagNodeName);
+ if (dagNodeName != null && dagNode == null) {
+ throw new IllegalArgumentException("Cannot find the Node: " + dagNodeName + " in DAG");
+ }
+ return getDirectPostNodes(dagNode).stream().map(DAGNode::getNodeName).collect(Collectors.toList());
+ }
+
+ /**
+ * Get the direct pre node of given dagNode, if the dagNode is null, return the nodes which doesn't have outDegrees.
+ * e.g. The DAG is:
+ * <pre>
+ * {@code
+ * 1 -> 2 -> 3
+ * 4 -> 5
+ * 6
+ * }
+ * </pre>
+ * <li> The pre node of 1 is empty.
+ * <li> The pre node of 3 is 2.
+ * <li> The pre node of null is 3,5,6.
+ *
+ * @param dagNode the node of the DAG, can be null.
+ * @return pre node list, sort by priority.
+ */
+ List<DAGNode> getDirectPreNodes(DAGNode dagNode);
+
+ /**
+ * Same with {@link #getDirectPreNodes(DAGNode)}.
+ * <p>
+ * If the dagNodeName is null, return the nodes which doesn't have outDegrees. Otherwise, return the pre nodes of
+ * the given dagNodeName. If the dagNodeName is not null and cannot find the node in DAG, throw IllegalArgumentException.
+ *
+ * @param dagNodeName task name, can be null.
+ * @return pre task name list, sort by priority.
+ * @throws IllegalArgumentException if the dagNodeName is not null and cannot find the node in DAG.
+ */
+ default List<DAGNode> getDirectPreNodes(String dagNodeName) {
+ DAGNode dagNode = getDAGNode(dagNodeName);
+ if (dagNodeName != null && dagNode == null) {
+ throw new IllegalArgumentException("Cannot find the Node: " + dagNodeName + " in DAG");
+ }
+ return getDirectPreNodes(dagNode);
+ }
+
+ /**
+ * Same with {@link #getDirectPreNodes(String)}. Return the pre node names.
+ *
+ * @param dagNodeName task name, can be null.
+ * @return pre task name list, sort by priority.
+ * @throws IllegalArgumentException if the dagNodeName is not null and cannot find the node in DAG.
+ */
+ default List<String> getDirectPreNodeNames(String dagNodeName) {
+ DAGNode dagNode = getDAGNode(dagNodeName);
+ if (dagNodeName != null && dagNode == null) {
+ throw new IllegalArgumentException("Cannot find the Node: " + dagNodeName + " in DAG");
+ }
+ return getDirectPreNodes(dagNode).stream().map(DAGNode::getNodeName).collect(Collectors.toList());
+ }
+
+ /**
+ * Get the node of the DAG by the node name.
+ *
+ * @param nodeName the node name.
+ * @return the node of the DAG, return null if cannot find the node.
+ */
+ DAGNode getDAGNode(String nodeName);
+
+}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/DAGEdge.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/DAGEdge.java
new file mode 100644
index 0000000000..8e2bdc2be6
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/DAGEdge.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.dag;
+
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * The edge of the DAG.
+ * <p>
+ * The edge contains the fromNodeName and the toNodeName, the fromNodeName is the node name of the from node, the toNodeName is the node name of the to node.
+ * <p>
+ * The formNodeName can be null, which means the edge is from the start node of the DAG.
+ * The toNodeName can be null, which means the edge is to the end node of the DAG.
+ * The fromNodeName and the toNodeName cannot be null at the same time.
+ */
+@Data
+@Builder
+@NoArgsConstructor
+public class DAGEdge {
+
+ private String fromNodeName;
+ private String toNodeName;
+
+ public DAGEdge(String fromNodeName, String toNodeName) {
+ if (fromNodeName == null && toNodeName == null) {
+ throw new IllegalArgumentException("fromNodeName and toNodeName cannot be null at the same time"
+ + "fromNodeName: " + fromNodeName + ", toNodeName: " + toNodeName);
+ }
+ if (fromNodeName != null && fromNodeName.equals(toNodeName)) {
+ throw new IllegalArgumentException("fromNodeName and toNodeName cannot be the same"
+ + "fromNodeName: " + fromNodeName + ", toNodeName: " + toNodeName);
+ }
+ this.fromNodeName = fromNodeName;
+ this.toNodeName = toNodeName;
+ }
+}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/DAGNode.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/DAGNode.java
new file mode 100644
index 0000000000..2e945a5463
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/DAGNode.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.dag;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.List;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+/**
+ * The node of the DAG.
+ * <p>
+ * The node contains the node name, the content of the node, the inDegrees and the outDegrees.
+ * The inDegrees is the edge from other nodes to the current node, the outDegrees is the edge from the current
+ * node to other nodes.
+ */
+@Getter
+@Builder
+@NoArgsConstructor
+public class DAGNode implements IDAGNode {
+
+ private String nodeName;
+
+ /**
+ * whether the node is skipped, default is false, which means the node is not skipped.
+ * If the node is skipped, the node will not be executed.
+ */
+ @Builder.Default
+ private boolean skip = false;
+
+ private List<DAGEdge> inDegrees;
+ private List<DAGEdge> outDegrees;
+
+ public DAGNode(String nodeName,
+ List<DAGEdge> inDegrees,
+ List<DAGEdge> outDegrees) {
+ this(nodeName, false, inDegrees, outDegrees);
+ }
+
+ public DAGNode(String nodeName,
+ boolean skip,
+ List<DAGEdge> inDegrees,
+ List<DAGEdge> outDegrees) {
+ if (StringUtils.isEmpty(nodeName)) {
+ throw new IllegalArgumentException("nodeName cannot be empty");
+ }
+
+ if (CollectionUtils.isNotEmpty(inDegrees)) {
+ inDegrees.forEach(dagEdge -> {
+ if (!nodeName.equals(dagEdge.getToNodeName())) {
+ throw new IllegalArgumentException(
+ "The toNodeName of inDegree should be the nodeName of the node: "
+ + nodeName + ", inDegree: " + dagEdge);
+ }
+ });
+ }
+
+ if (CollectionUtils.isNotEmpty(outDegrees)) {
+ outDegrees.forEach(dagEdge -> {
+ if (!nodeName.equals(dagEdge.getFromNodeName())) {
+ throw new IllegalArgumentException(
+ "The fromNodeName of outDegree should be the nodeName of the node: "
+ + nodeName + ", outDegree: " + dagEdge);
+ }
+ });
+ }
+
+ this.nodeName = nodeName;
+ this.inDegrees = inDegrees;
+ this.outDegrees = outDegrees;
+ this.skip = skip;
+ }
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/DAGNodeDefinition.java
similarity index 72%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/DAGNodeDefinition.java
index ac37c94438..b72d8ee6ba 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/DAGNodeDefinition.java
@@ -15,12 +15,21 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class DAGNodeDefinition {
+
+ private String nodeName;
+
+ private boolean skip;
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/IDAGNode.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/IDAGNode.java
index ac37c94438..c3d85ae3ac 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/IDAGNode.java
@@ -15,12 +15,18 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+import java.util.List;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+public interface IDAGNode {
+
+ String getNodeName();
+
+ boolean isSkip();
+
+ List<DAGEdge> getInDegrees();
+
+ List<DAGEdge> getOutDegrees();
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/IDAGNodeAction.java
similarity index 76%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/IDAGNodeAction.java
index ac37c94438..9b6684a37f 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/IDAGNodeAction.java
@@ -15,12 +15,21 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.dag;
-public class TaskExecutionContextCreateException extends MasterException {
+/**
+ * The IDAGNodeAction represent the action of a DAG node.
+ */
+public interface IDAGNodeAction {
+
+ void run();
+
+ void kill();
+
+ void pause();
+
+ void success();
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ void failure();
}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/WorkflowDAG.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/WorkflowDAG.java
new file mode 100644
index 0000000000..c31749af93
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/WorkflowDAG.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.dag;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * The IWorkflowDAG represent the DAG of a workflow.
+ */
+public class WorkflowDAG implements DAG {
+
+ private final Map<String, DAGNode> dagNodeMap;
+
+ public WorkflowDAG(List<DAGNode> dagNodes) {
+ this.dagNodeMap = dagNodes.stream().collect(Collectors.toMap(DAGNode::getNodeName, Function.identity()));
+ }
+
+ @Override
+ public List<DAGNode> getDirectPostNodes(DAGNode dagNode) {
+ final String nodeName = dagNode.getNodeName();
+ if (!dagNodeMap.containsKey(nodeName)) {
+ return Collections.emptyList();
+ }
+ DAGNode node = dagNodeMap.get(nodeName);
+ List<DAGNode> dagNodes = new ArrayList<>();
+ for (DAGEdge edge : node.getOutDegrees()) {
+ if (dagNodeMap.containsKey(edge.getToNodeName())) {
+ dagNodes.add(dagNodeMap.get(edge.getToNodeName()));
+ }
+ }
+ return dagNodes;
+ }
+
+ @Override
+ public List<DAGNode> getDirectPreNodes(DAGNode dagNode) {
+ final String nodeName = dagNode.getNodeName();
+ if (!dagNodeMap.containsKey(nodeName)) {
+ return Collections.emptyList();
+ }
+ DAGNode node = dagNodeMap.get(nodeName);
+ List<DAGNode> dagNodes = new ArrayList<>();
+ for (DAGEdge edge : node.getInDegrees()) {
+ if (dagNodeMap.containsKey(edge.getFromNodeName())) {
+ dagNodes.add(dagNodeMap.get(edge.getFromNodeName()));
+ }
+ }
+ return dagNodes;
+ }
+
+ @Override
+ public DAGNode getDAGNode(String nodeName) {
+ return dagNodeMap.get(nodeName);
+ }
+
+}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/WorkflowDAGBuilder.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/WorkflowDAGBuilder.java
new file mode 100644
index 0000000000..fbf666d947
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/dag/WorkflowDAGBuilder.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.dag;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Used to build WorkflowDAG, you need to add TaskNode first, then add TaskEdge.
+ * After adding all the TaskNodes and TaskEdges, you can call the build method to get the WorkflowDAG.
+ * <p>
+ * Example:
+ * <pre>
+ * {@code
+ * WorkflowDAG workflowDAG = WorkflowDAGBuilder.newBuilder()
+ * .addTaskNode(taskNodeA)
+ * .addTaskNode(taskNodeB)
+ * .addTaskNode(taskNodeC)
+ * .addTaskEdge(edgeAB)
+ * .addTaskEdge(edgeBC)
+ * .build();
+ * }
+ * </pre>
+ */
+public class WorkflowDAGBuilder {
+
+ private final Map<String, DAGNode> taskNameMap;
+
+ private WorkflowDAGBuilder() {
+ this.taskNameMap = new HashMap<>();
+ }
+
+ public static WorkflowDAGBuilder newBuilder() {
+ return new WorkflowDAGBuilder();
+ }
+
+ public WorkflowDAGBuilder addTaskNodes(List<DAGNodeDefinition> dagNodes) {
+ dagNodes.forEach(this::addTaskNode);
+ return this;
+ }
+
+ public WorkflowDAGBuilder addTaskNode(DAGNodeDefinition dagNodeDefinition) {
+ String nodeName = dagNodeDefinition.getNodeName();
+ if (taskNameMap.containsKey(nodeName)) {
+ throw new IllegalArgumentException("TaskNode with name " + nodeName + " already exists");
+ }
+
+ DAGNode taskNode = DAGNode.builder()
+ .nodeName(nodeName)
+ .inDegrees(new ArrayList<>())
+ .outDegrees(new ArrayList<>())
+ .skip(dagNodeDefinition.isSkip())
+ .build();
+ taskNameMap.put(nodeName, taskNode);
+ return this;
+ }
+
+ public WorkflowDAGBuilder addTaskEdges(List<DAGEdge> processTaskRelations) {
+ processTaskRelations.forEach(this::addTaskEdge);
+ return this;
+ }
+
+ public WorkflowDAGBuilder addTaskEdge(DAGEdge dagEdge) {
+ String fromNodeName = dagEdge.getFromNodeName();
+ String toNodeName = dagEdge.getToNodeName();
+
+ if (taskNameMap.containsKey(fromNodeName)) {
+ DAGNode fromTask = taskNameMap.get(fromNodeName);
+ if (fromTask.getOutDegrees().contains(dagEdge)) {
+ throw new IllegalArgumentException(
+ "Edge from " + fromNodeName + " to " + toNodeName + " already exists");
+ }
+ fromTask.getOutDegrees().add(dagEdge);
+ }
+ if (taskNameMap.containsKey(toNodeName)) {
+ DAGNode toTask = taskNameMap.get(toNodeName);
+ if (toTask.getInDegrees().contains(dagEdge)) {
+ throw new IllegalArgumentException(
+ "Edge from " + fromNodeName + " to " + toNodeName + " already exists");
+ }
+ toTask.getInDegrees().add(dagEdge);
+ }
+ return this;
+ }
+
+ public WorkflowDAG build() {
+ return new WorkflowDAG(new ArrayList<>(taskNameMap.values()));
+ }
+
+}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/DAGEngine.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/DAGEngine.java
new file mode 100644
index 0000000000..d5273367ef
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/DAGEngine.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.engine;
+
+import org.apache.dolphinscheduler.workflow.engine.dag.DAGNode;
+import org.apache.dolphinscheduler.workflow.engine.event.TaskOperationEvent;
+import org.apache.dolphinscheduler.workflow.engine.event.TaskOperationType;
+import org.apache.dolphinscheduler.workflow.engine.workflow.ITaskExecutionRunnable;
+import org.apache.dolphinscheduler.workflow.engine.workflow.ITaskExecutionRunnableFactory;
+import org.apache.dolphinscheduler.workflow.engine.workflow.IWorkflowExecutionContext;
+import org.apache.dolphinscheduler.workflow.engine.workflow.IWorkflowExecutionDAG;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class DAGEngine implements IDAGEngine {
+
+ private final IWorkflowExecutionContext workflowExecutionContext;
+
+ private final ITaskExecutionRunnableFactory taskExecutionRunnableFactory;
+
+ public DAGEngine(IWorkflowExecutionContext workflowExecutionContext,
+ ITaskExecutionRunnableFactory taskExecutionRunnableFactory) {
+ this.workflowExecutionContext = workflowExecutionContext;
+ this.taskExecutionRunnableFactory = taskExecutionRunnableFactory;
+ }
+
+ @Override
+ public void triggerNextTasks(String parentTaskNodeName) {
+ workflowExecutionContext.getWorkflowExecutionDAG()
+ .getDirectPostNodeNames(parentTaskNodeName)
+ .forEach(this::triggerTask);
+ }
+
+ @Override
+ public void triggerTask(String taskName) {
+ IWorkflowExecutionDAG workflowExecutionDAG = workflowExecutionContext.getWorkflowExecutionDAG();
+ DAGNode dagNode = workflowExecutionDAG.getDAGNode(taskName);
+ if (dagNode == null) {
+ log.error("Cannot find the DAGNode for task: {}", taskName);
+ return;
+ }
+
+ // todo: Use condition check?
+ // How to make sure the
+ if (!workflowExecutionDAG.isTaskAbleToBeTriggered(taskName)) {
+ log.info("The task: {} is not able to be triggered", taskName);
+ return;
+ }
+
+ if (dagNode.isSkip()) {
+ log.info("The task: {} is skipped", taskName);
+ triggerNextTasks(taskName);
+ return;
+ }
+
+ ITaskExecutionRunnable taskExecutionRunnable =
+ taskExecutionRunnableFactory.createTaskExecutionRunnable(taskName, workflowExecutionContext);
+ workflowExecutionDAG.storeTaskExecutionRunnable(taskExecutionRunnable);
+ TaskOperationEvent taskOperationEvent = TaskOperationEvent.builder()
+ .taskExecutionRunnable(taskExecutionRunnable)
+ .taskOperationType(TaskOperationType.RUN)
+ .build();
+ workflowExecutionContext.getEventRepository().storeEventToTail(taskOperationEvent);
+ }
+
+ @Override
+ public void failoverTask(Integer taskInstanceId) {
+ IWorkflowExecutionDAG workflowExecutionDAG = workflowExecutionContext.getWorkflowExecutionDAG();
+ ITaskExecutionRunnable taskExecutionRunnable =
+ workflowExecutionDAG.getTaskExecutionRunnableById(taskInstanceId);
+ if (taskExecutionRunnable == null) {
+ log.error("Cannot find the ITaskExecutionRunnable for taskInstance: {}", taskInstanceId);
+ return;
+ }
+ ITaskExecutionRunnable failoverTaskExecutionRunnable = taskExecutionRunnableFactory
+ .createFailoverTaskExecutionRunnable(taskExecutionRunnable, workflowExecutionContext);
+ workflowExecutionDAG.storeTaskExecutionRunnable(failoverTaskExecutionRunnable);
+
+ TaskOperationEvent taskOperationEvent = TaskOperationEvent.builder()
+ .taskExecutionRunnable(taskExecutionRunnable)
+ .taskOperationType(TaskOperationType.FAILOVER)
+ .build();
+ workflowExecutionContext.getEventRepository().storeEventToTail(taskOperationEvent);
+ }
+
+ @Override
+ public void retryTask(Integer taskInstanceId) {
+ IWorkflowExecutionDAG workflowExecutionDAG = workflowExecutionContext.getWorkflowExecutionDAG();
+ ITaskExecutionRunnable taskExecutionRunnable =
+ workflowExecutionDAG.getTaskExecutionRunnableById(taskInstanceId);
+ if (taskExecutionRunnable == null) {
+ log.error("Cannot find the ITaskExecutionRunnable for taskInstance: {}", taskInstanceId);
+ return;
+ }
+ ITaskExecutionRunnable retryTaskExecutionRunnable = taskExecutionRunnableFactory
+ .createRetryTaskExecutionRunnable(taskExecutionRunnable, workflowExecutionContext);
+ workflowExecutionDAG.storeTaskExecutionRunnable(retryTaskExecutionRunnable);
+
+ TaskOperationEvent taskOperationEvent = TaskOperationEvent.builder()
+ .taskExecutionRunnable(taskExecutionRunnable)
+ .taskOperationType(TaskOperationType.RETRY)
+ .build();
+ workflowExecutionContext.getEventRepository().storeEventToTail(taskOperationEvent);
+ }
+
+ @Override
+ public void pauseAllTask() {
+ workflowExecutionContext.getWorkflowExecutionDAG()
+ .getActiveTaskExecutionRunnable()
+ .stream()
+ .map(taskExecutionRunnable -> taskExecutionRunnable.getTaskExecutionContext().getTaskInstance().getId())
+ .forEach(this::pauseTask);
+ }
+
+ @Override
+ public void pauseTask(Integer taskInstanceId) {
+ ITaskExecutionRunnable taskExecutionRunnable =
+ workflowExecutionContext.getWorkflowExecutionDAG().getTaskExecutionRunnableById(taskInstanceId);
+ if (taskExecutionRunnable == null) {
+ log.error("Cannot find the ITaskExecutionRunnable for taskInstance: {}", taskInstanceId);
+ return;
+ }
+ TaskOperationEvent taskOperationEvent = TaskOperationEvent.builder()
+ .taskExecutionRunnable(taskExecutionRunnable)
+ .taskOperationType(TaskOperationType.PAUSE)
+ .build();
+ workflowExecutionContext.getEventRepository().storeEventToTail(taskOperationEvent);
+ }
+
+ @Override
+ public void killAllTask() {
+ workflowExecutionContext.getWorkflowExecutionDAG()
+ .getActiveTaskExecutionRunnable()
+ .stream()
+ .map(taskExecutionRunnable -> taskExecutionRunnable.getTaskExecutionContext().getTaskInstance().getId())
+ .forEach(this::killTask);
+ }
+
+ @Override
+ public void killTask(Integer taskInstanceId) {
+ ITaskExecutionRunnable taskExecutionRunnable =
+ workflowExecutionContext.getWorkflowExecutionDAG().getTaskExecutionRunnableById(taskInstanceId);
+ if (taskExecutionRunnable == null) {
+ log.error("Cannot find the ITaskExecutionRunnable for taskInstance: {}", taskInstanceId);
+ return;
+ }
+
+ TaskOperationEvent taskOperationEvent = TaskOperationEvent.builder()
+ .taskExecutionRunnable(taskExecutionRunnable)
+ .taskOperationType(TaskOperationType.KILL)
+ .build();
+ workflowExecutionContext.getEventRepository().storeEventToTail(taskOperationEvent);
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/DAGEngineFactory.java
similarity index 51%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/DAGEngineFactory.java
index ac37c94438..c07ca6ffbb 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/DAGEngineFactory.java
@@ -15,12 +15,24 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.engine;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.workflow.engine.workflow.ITaskExecutionRunnableFactory;
+import org.apache.dolphinscheduler.workflow.engine.workflow.IWorkflowExecutionContext;
- public TaskExecutionContextCreateException(String message) {
- super(message);
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class DAGEngineFactory implements IDAGEngineFactory {
+
+ private final ITaskExecutionRunnableFactory taskExecutionRunnableFactory;
+
+ public DAGEngineFactory(ITaskExecutionRunnableFactory taskExecutionRunnableFactory) {
+ this.taskExecutionRunnableFactory = taskExecutionRunnableFactory;
}
+ @Override
+ public IDAGEngine createDAGEngine(IWorkflowExecutionContext workflowExecutionContext) {
+ return new DAGEngine(workflowExecutionContext, taskExecutionRunnableFactory);
+ }
}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/IDAGEngine.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/IDAGEngine.java
new file mode 100644
index 0000000000..0971e2a179
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/IDAGEngine.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.engine;
+
+import org.apache.dolphinscheduler.workflow.engine.workflow.IWorkflowExecutionDAG;
+
+/**
+ * The IDAGEngine is responsible for triggering, killing, pausing, and finalizing task in {@link org.apache.dolphinscheduler.workflow.engine.dag.WorkflowDAG}.
+ * <p>All DAG operation should directly use the method in IDAGEngine, new {@link IWorkflowExecutionDAG} should be triggered by new IDAGEngine.
+ */
+public interface IDAGEngine {
+
+ /**
+ * Trigger the tasks which are post of the given task.
+ * <P> If there are no task after the given taskNode, will try to finish the WorkflowExecutionRunnable.
+ * <p> If the
+ *
+ * @param parentTaskNodeName the parent task name
+ */
+ void triggerNextTasks(String parentTaskNodeName);
+
+ /**
+ * Trigger the given task
+ *
+ * @param taskName task name
+ */
+ void triggerTask(String taskName);
+
+ /**
+ * Failover the given task.
+ *
+ * @param taskInstanceId taskInstanceId
+ */
+ void failoverTask(Integer taskInstanceId);
+
+ /**
+ * Retry the given task.
+ *
+ * @param taskInstanceId taskInstanceId
+ */
+ void retryTask(Integer taskInstanceId);
+
+ void pauseAllTask();
+
+ /**
+ * Pause the given task.
+ */
+ void pauseTask(Integer taskInstanceId);
+
+ void killAllTask();
+
+ /**
+ * Kill the given task.
+ */
+ void killTask(Integer taskId);
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/IDAGEngineFactory.java
similarity index 75%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/IDAGEngineFactory.java
index ac37c94438..c0d134ad5c 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/IDAGEngineFactory.java
@@ -15,12 +15,12 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.engine;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.workflow.engine.workflow.IWorkflowExecutionContext;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+public interface IDAGEngineFactory {
+
+ IDAGEngine createDAGEngine(IWorkflowExecutionContext workflowExecutionContext);
}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/IWorkflowEngine.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/IWorkflowEngine.java
new file mode 100644
index 0000000000..d1df4df7f5
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/IWorkflowEngine.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.engine;
+
+import org.apache.dolphinscheduler.workflow.engine.exception.WorkflowExecuteRunnableNotFoundException;
+import org.apache.dolphinscheduler.workflow.engine.workflow.IWorkflowExecutionRunnable;
+
+/**
+ * The WorkflowEngine is responsible for starting, stopping, pausing, and finalizing workflows.
+ */
+public interface IWorkflowEngine {
+
+ /**
+ * Trigger a workflow to start.
+ *
+ * @param workflowExecuteRunnable the workflow to start
+ */
+ void triggerWorkflow(IWorkflowExecutionRunnable workflowExecuteRunnable);
+
+ /**
+ * Pause a workflow instance.
+ *
+ * @param workflowInstanceId the ID of the workflow to pause
+ * @throws WorkflowExecuteRunnableNotFoundException if the workflow is not found
+ */
+ void pauseWorkflow(Integer workflowInstanceId);
+
+ /**
+ * Kill a workflow instance.
+ *
+ * @param workflowInstanceId the ID of the workflow to stop
+ * @throws WorkflowExecuteRunnableNotFoundException if the workflow is not found
+ */
+ void killWorkflow(Integer workflowInstanceId);
+
+ /**
+ * Finalize a workflow instance. Once a workflow has been finalized, then it cannot receive new operation, and will be removed from memory.
+ *
+ * @param workflowInstanceId the ID of the workflow to finalize
+ */
+ void finalizeWorkflow(Integer workflowInstanceId);
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/IWorkflowEngineFactory.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/IWorkflowEngineFactory.java
index ac37c94438..b011e0d16a 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/IWorkflowEngineFactory.java
@@ -15,12 +15,10 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.engine;
-public class TaskExecutionContextCreateException extends MasterException {
+public interface IWorkflowEngineFactory {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ IWorkflowEngine createWorkflowEngine();
}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/WorkflowEngine.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/WorkflowEngine.java
new file mode 100644
index 0000000000..92bec2fe1f
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/WorkflowEngine.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.engine;
+
+import org.apache.dolphinscheduler.workflow.engine.event.WorkflowOperationEvent;
+import org.apache.dolphinscheduler.workflow.engine.exception.WorkflowExecuteRunnableNotFoundException;
+import org.apache.dolphinscheduler.workflow.engine.workflow.IWorkflowExecuteRunnableRepository;
+import org.apache.dolphinscheduler.workflow.engine.workflow.IWorkflowExecutionContext;
+import org.apache.dolphinscheduler.workflow.engine.workflow.IWorkflowExecutionRunnable;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class WorkflowEngine implements IWorkflowEngine {
+
+ private final IWorkflowExecuteRunnableRepository workflowExecuteRunnableRepository;
+
+ public WorkflowEngine(IWorkflowExecuteRunnableRepository workflowExecuteRunnableRepository) {
+ this.workflowExecuteRunnableRepository = workflowExecuteRunnableRepository;
+ }
+
+ @Override
+ public void triggerWorkflow(IWorkflowExecutionRunnable workflowExecuteRunnable) {
+ IWorkflowExecutionContext workflowExecutionContext = workflowExecuteRunnable.getWorkflowExecutionContext();
+ Integer workflowInstanceId = workflowExecutionContext.getWorkflowInstanceId();
+ log.info("Triggering WorkflowExecutionRunnable: {}", workflowExecutionContext.getWorkflowInstanceName());
+ workflowExecuteRunnableRepository.storeWorkflowExecutionRunnable(workflowExecuteRunnable);
+ workflowExecuteRunnable.storeEventToTail(WorkflowOperationEvent.triggerEvent(workflowInstanceId));
+ }
+
+ @Override
+ public void pauseWorkflow(Integer workflowInstanceId) {
+ IWorkflowExecutionRunnable workflowExecuteRunnable =
+ workflowExecuteRunnableRepository.getWorkflowExecutionRunnableById(workflowInstanceId);
+ if (workflowExecuteRunnable == null) {
+ throw new WorkflowExecuteRunnableNotFoundException(workflowInstanceId);
+ }
+ log.info("Pausing WorkflowExecutionRunnable: {}",
+ workflowExecuteRunnable.getWorkflowExecutionContext().getWorkflowInstanceName());
+ workflowExecuteRunnable.storeEventToTail(WorkflowOperationEvent.pauseEvent(workflowInstanceId));
+ }
+
+ @Override
+ public void killWorkflow(Integer workflowInstanceId) {
+ IWorkflowExecutionRunnable workflowExecuteRunnable =
+ workflowExecuteRunnableRepository.getWorkflowExecutionRunnableById(workflowInstanceId);
+ if (workflowExecuteRunnable == null) {
+ throw new WorkflowExecuteRunnableNotFoundException(workflowInstanceId);
+ }
+ log.info("Killing WorkflowExecutionRunnable: {}",
+ workflowExecuteRunnable.getWorkflowExecutionContext().getWorkflowInstanceName());
+ workflowExecuteRunnable.storeEventToTail(WorkflowOperationEvent.killEvent(workflowInstanceId));
+ }
+
+ @Override
+ public void finalizeWorkflow(Integer workflowInstanceId) {
+ IWorkflowExecutionRunnable workflowExecutionRunnable =
+ workflowExecuteRunnableRepository.getWorkflowExecutionRunnableById(workflowInstanceId);
+ if (workflowExecutionRunnable == null) {
+ return;
+ }
+ log.info("Finalizing WorkflowExecutionRunnable: {}",
+ workflowExecutionRunnable.getWorkflowExecutionContext().getWorkflowInstanceName());
+ workflowExecuteRunnableRepository.removeWorkflowExecutionRunnable(workflowInstanceId);
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/WorkflowEngineFactory.java
similarity index 67%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/WorkflowEngineFactory.java
index ac37c94438..5a32510bd1 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/engine/WorkflowEngineFactory.java
@@ -15,12 +15,14 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.engine;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.workflow.engine.workflow.SingletonWorkflowExecuteRunnableRepository;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+public class WorkflowEngineFactory implements IWorkflowEngineFactory {
+ @Override
+ public IWorkflowEngine createWorkflowEngine() {
+ return new WorkflowEngine(SingletonWorkflowExecuteRunnableRepository.getInstance());
+ }
}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/EventEngine.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/EventEngine.java
new file mode 100644
index 0000000000..35bfe079c5
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/EventEngine.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.event;
+
+import org.apache.dolphinscheduler.common.constants.Constants;
+import org.apache.dolphinscheduler.common.thread.BaseDaemonThread;
+import org.apache.dolphinscheduler.common.thread.ThreadUtils;
+import org.apache.dolphinscheduler.workflow.engine.workflow.IWorkflowExecuteRunnableRepository;
+import org.apache.dolphinscheduler.workflow.engine.workflow.IWorkflowExecutionContext;
+import org.apache.dolphinscheduler.workflow.engine.workflow.IWorkflowExecutionRunnable;
+
+import org.apache.commons.lang3.time.StopWatch;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.slf4j.MDC;
+
+@Slf4j
+public class EventEngine extends BaseDaemonThread {
+
+ private final IWorkflowExecuteRunnableRepository workflowExecuteRunnableRepository;
+
+ private final EventFirer eventFirer;
+
+ private final Set<Integer> firingWorkflowInstanceIds;
+
+ public EventEngine(IWorkflowExecuteRunnableRepository workflowExecuteRunnableRepository,
+ EventFirer eventFirer) {
+ super("EventEngine");
+ this.workflowExecuteRunnableRepository = workflowExecuteRunnableRepository;
+ this.eventFirer = eventFirer;
+ this.firingWorkflowInstanceIds = ConcurrentHashMap.newKeySet();
+ }
+
+ @Override
+ public synchronized void start() {
+ super.start();
+ log.info(getClass().getName() + " started");
+ }
+
+ @Override
+ public void run() {
+ for (;;) {
+ try {
+ StopWatch stopWatch = StopWatch.createStarted();
+ fireAllActiveEvents();
+ stopWatch.stop();
+ log.info("Fire all active events cost: {} ms", stopWatch.getTime());
+ this.wait(5_000);
+ } catch (Throwable throwable) {
+ log.error("Fire active event error", throwable);
+ ThreadUtils.sleep(3_000);
+ }
+ }
+ }
+
+ public void fireAllActiveEvents() {
+ Collection<IWorkflowExecutionRunnable> workflowExecutionRunnableCollection =
+ workflowExecuteRunnableRepository.getActiveWorkflowExecutionRunnable();
+ for (IWorkflowExecutionRunnable workflowExecutionRunnable : workflowExecutionRunnableCollection) {
+ IWorkflowExecutionContext workflowExecutionContext =
+ workflowExecutionRunnable.getWorkflowExecutionContext();
+ final Integer workflowInstanceId = workflowExecutionContext.getWorkflowInstanceId();
+ final String workflowInstanceName = workflowExecutionContext.getWorkflowInstanceName();
+ try {
+ MDC.put(Constants.WORKFLOW_INSTANCE_ID_MDC_KEY, String.valueOf(workflowInstanceId));
+ if (firingWorkflowInstanceIds.contains(workflowInstanceId)) {
+ log.debug("WorkflowExecutionRunnable: {} is already in firing", workflowInstanceName);
+ return;
+ }
+ IEventRepository workflowEventRepository = workflowExecutionRunnable.getEventRepository();
+ firingWorkflowInstanceIds.add(workflowInstanceId);
+ eventFirer.fireActiveEvents(workflowEventRepository)
+ .whenComplete((fireCount, ex) -> {
+ firingWorkflowInstanceIds.remove(workflowInstanceId);
+ if (ex != null) {
+ log.error("Fire event for WorkflowExecutionRunnable: {} error", workflowInstanceName,
+ ex);
+ } else {
+ if (fireCount > 0) {
+ log.info("Fire {} events for WorkflowExecutionRunnable: {} success", fireCount,
+ workflowInstanceName);
+ }
+ }
+ });
+ } finally {
+ MDC.remove(Constants.WORKFLOW_INSTANCE_ID_MDC_KEY);
+ }
+ }
+ }
+
+}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/EventFirer.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/EventFirer.java
new file mode 100644
index 0000000000..0026bd0c21
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/EventFirer.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.event;
+
+import org.apache.dolphinscheduler.common.thread.ThreadUtils;
+import org.apache.dolphinscheduler.workflow.engine.utils.ExceptionUtils;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class EventFirer implements IEventFirer {
+
+ private final IEventOperatorManager<IEvent> eventOperatorManager;
+
+ private final ThreadPoolExecutor eventFireThreadPool;
+
+ public EventFirer(IEventOperatorManager<IEvent> eventOperatorManager, int eventFireThreadPoolSize) {
+ this.eventOperatorManager = eventOperatorManager;
+ this.eventFireThreadPool =
+ ThreadUtils.newDaemonFixedThreadExecutor("EventFireThreadPool", eventFireThreadPoolSize);
+ }
+
+ @Override
+ public CompletableFuture<Integer> fireActiveEvents(IEventRepository eventRepository) {
+ if (eventRepository.getEventSize() == 0) {
+ return CompletableFuture.completedFuture(0);
+ }
+ return CompletableFuture.supplyAsync(() -> {
+ int fireCount = 0;
+ for (;;) {
+ IEvent event = eventRepository.poolEvent();
+ if (event == null) {
+ break;
+ }
+
+ if (event instanceof IAsyncEvent) {
+ fireAsyncEvent(event);
+ fireCount++;
+ continue;
+ }
+ try {
+ fireSyncEvent(event);
+ fireCount++;
+ } catch (Exception ex) {
+ if (ExceptionUtils.isDatabaseConnectedFailedException(ex)) {
+ // If the event is failed due to cannot connect to DB, we should retry it
+ eventRepository.storeEventToHead(event);
+ }
+ throw ex;
+ }
+ }
+ return fireCount;
+ }, eventFireThreadPool);
+ }
+
+ private void fireAsyncEvent(IEvent event) {
+ CompletableFuture.runAsync(() -> {
+ log.info("Begin fire IAsyncEvent: {}", event);
+ eventOperatorManager.getEventOperator(event).handleEvent(event);
+ log.info("Success fire IAsyncEvent: {}", event);
+ }, eventFireThreadPool).exceptionally(ex -> {
+ log.error("Failed to fire IAsyncEvent: {}", event, ex);
+ return null;
+ });
+ }
+
+ private void fireSyncEvent(IEvent event) {
+ log.info("Begin fire SyncEvent: {}", event);
+ eventOperatorManager.getEventOperator(event).handleEvent(event);
+ log.info("Success fire SyncEvent: {}", event);
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/EventOperatorManager.java
similarity index 65%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/EventOperatorManager.java
index ac37c94438..fb0e3d0a50 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/EventOperatorManager.java
@@ -15,12 +15,22 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.event;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.extern.slf4j.Slf4j;
- public TaskExecutionContextCreateException(String message) {
- super(message);
+import org.springframework.stereotype.Component;
+
+/**
+ * The event operator manager interface used to get {@link ITaskEventOperator}.
+ */
+@Slf4j
+@Component
+public class EventOperatorManager implements IEventOperatorManager<IEvent> {
+
+ @Override
+ public IEventOperator<IEvent> getEventOperator(IEvent event) {
+ return null;
}
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IAsyncEvent.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IAsyncEvent.java
index ac37c94438..2de1ebb9cc 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IAsyncEvent.java
@@ -15,12 +15,10 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
-
-public class TaskExecutionContextCreateException extends MasterException {
-
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+package org.apache.dolphinscheduler.workflow.engine.event;
+/**
+ * Mark the event as AsyncEvent, if the event is marked as AsyncEvent, the event will be handled asynchronously and we don't .
+ */
+public interface IAsyncEvent {
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IDelayEvent.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IDelayEvent.java
index ac37c94438..05a883d2ca 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IDelayEvent.java
@@ -15,12 +15,12 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.event;
-public class TaskExecutionContextCreateException extends MasterException {
+public interface IDelayEvent {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ long getEventCreateTime();
+
+ long getDelayTime();
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IEvent.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IEvent.java
index ac37c94438..22fd7ec940 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IEvent.java
@@ -15,12 +15,8 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.event;
-public class TaskExecutionContextCreateException extends MasterException {
-
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+public interface IEvent {
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IEventFirer.java
similarity index 66%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IEventFirer.java
index ac37c94438..131bac9412 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IEventFirer.java
@@ -15,12 +15,21 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.event;
-public class TaskExecutionContextCreateException extends MasterException {
+import java.util.concurrent.CompletableFuture;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+/**
+ * The event firer interface used to fire event.
+ *
+ */
+public interface IEventFirer {
+
+ /**
+ * Fire all active events in the event repository
+ *
+ * @return the count of fired success events
+ */
+ CompletableFuture<Integer> fireActiveEvents(IEventRepository eventRepository);
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IEventOperator.java
similarity index 75%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IEventOperator.java
index ac37c94438..be65031c06 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IEventOperator.java
@@ -15,12 +15,18 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.event;
-public class TaskExecutionContextCreateException extends MasterException {
+/**
+ * The event operator interface used to handle event.
+ */
+public interface IEventOperator<E> {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ /**
+ * Handle the given event
+ *
+ * @param event event
+ */
+ void handleEvent(E event);
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IEventOperatorManager.java
similarity index 67%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IEventOperatorManager.java
index ac37c94438..68cffa4ecc 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IEventOperatorManager.java
@@ -15,12 +15,19 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.event;
-public class TaskExecutionContextCreateException extends MasterException {
+/**
+ * The event operator manager interface used to get event operator.
+ */
+public interface IEventOperatorManager<E> {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ /**
+ * Get the {@link IEventOperator} for the given event.
+ *
+ * @param event event
+ * @return event operator for the given event
+ */
+ IEventOperator<E> getEventOperator(E event);
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IEventRepository.java
similarity index 69%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IEventRepository.java
index ac37c94438..f96df57680 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IEventRepository.java
@@ -15,12 +15,23 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.event;
-public class TaskExecutionContextCreateException extends MasterException {
+import java.util.List;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+/**
+ * The event repository interface used to store event.
+ */
+public interface IEventRepository {
+
+ void storeEventToTail(IEvent event);
+
+ void storeEventToHead(IEvent event);
+
+ IEvent poolEvent();
+
+ int getEventSize();
+
+ List<IEvent> getAllEvent();
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/ISyncEvent.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/ISyncEvent.java
index ac37c94438..5b4ecb6162 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/ISyncEvent.java
@@ -15,12 +15,7 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
-
-public class TaskExecutionContextCreateException extends MasterException {
-
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+package org.apache.dolphinscheduler.workflow.engine.event;
+public interface ISyncEvent {
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/ITaskEvent.java
similarity index 76%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/ITaskEvent.java
index ac37c94438..dd1f315aed 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/ITaskEvent.java
@@ -15,12 +15,12 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.event;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.workflow.engine.workflow.ITaskExecutionRunnable;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+public interface ITaskEvent extends IEvent {
+
+ ITaskExecutionRunnable getTaskExecutionRunnable();
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/ITaskEventOperator.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/ITaskEventOperator.java
index ac37c94438..f015a61e2c 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/ITaskEventOperator.java
@@ -15,12 +15,8 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.event;
-public class TaskExecutionContextCreateException extends MasterException {
-
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+public interface ITaskEventOperator<E extends ITaskEvent> extends IEventOperator<E> {
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IWorkflowEvent.java
similarity index 73%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IWorkflowEvent.java
index ac37c94438..304776b582 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IWorkflowEvent.java
@@ -15,12 +15,15 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.event;
-public class TaskExecutionContextCreateException extends MasterException {
+public interface IWorkflowEvent extends IEvent {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ /**
+ * The id of WorkflowInstance which the event is related to
+ *
+ * @return workflowInstanceId, shouldn't be null
+ */
+ Integer getWorkflowInstanceId();
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IWorkflowEventOperator.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IWorkflowEventOperator.java
index ac37c94438..48dc80ee65 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/IWorkflowEventOperator.java
@@ -15,12 +15,9 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
-
-public class TaskExecutionContextCreateException extends MasterException {
-
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+package org.apache.dolphinscheduler.workflow.engine.event;
+public interface IWorkflowEventOperator<E extends IWorkflowEvent>
+ extends
+ IEventOperator<E> {
}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/MemoryEventRepository.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/MemoryEventRepository.java
new file mode 100644
index 0000000000..f6f2c239fc
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/MemoryEventRepository.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.event;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.LinkedBlockingDeque;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class MemoryEventRepository implements IEventRepository {
+
+ private final LinkedBlockingDeque<IEvent> eventQueue;
+
+ private MemoryEventRepository() {
+ this.eventQueue = new LinkedBlockingDeque<>();
+ }
+
+ public static MemoryEventRepository newInstance() {
+ return new MemoryEventRepository();
+ }
+
+ @Override
+ public void storeEventToTail(IEvent event) {
+ log.info("Store event to tail: {}", event);
+ eventQueue.offerLast(event);
+ }
+
+ @Override
+ public void storeEventToHead(IEvent event) {
+ eventQueue.offerFirst(event);
+ }
+
+ @Override
+ public IEvent poolEvent() {
+ return eventQueue.poll();
+ }
+
+ @Override
+ public int getEventSize() {
+ return eventQueue.size();
+ }
+
+ public List<IEvent> getAllEvent() {
+ return new ArrayList<>(eventQueue);
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/TaskOperationEvent.java
similarity index 62%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/TaskOperationEvent.java
index ac37c94438..1afb6ee7d8 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/TaskOperationEvent.java
@@ -15,12 +15,23 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.event;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.workflow.engine.workflow.ITaskExecutionRunnable;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TaskOperationEvent implements ITaskEvent, ISyncEvent {
+
+ private ITaskExecutionRunnable taskExecutionRunnable;
+
+ private TaskOperationType taskOperationType;
}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/TaskOperationEventOperator.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/TaskOperationEventOperator.java
new file mode 100644
index 0000000000..e17868822c
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/TaskOperationEventOperator.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.event;
+
+import org.apache.dolphinscheduler.workflow.engine.workflow.ITaskExecutionRunnable;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class TaskOperationEventOperator implements ITaskEventOperator<TaskOperationEvent> {
+
+ @Override
+ public void handleEvent(TaskOperationEvent event) {
+ ITaskExecutionRunnable taskExecutionRunnable = event.getTaskExecutionRunnable();
+ switch (event.getTaskOperationType()) {
+ case RUN:
+ taskExecutionRunnable.dispatch();
+ break;
+ case KILL:
+ taskExecutionRunnable.kill();
+ break;
+ case PAUSE:
+ taskExecutionRunnable.pause();
+ break;
+ default:
+ log.error("Unknown TaskOperationType for event: {}", event);
+ }
+ }
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/TaskOperationType.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/TaskOperationType.java
index ac37c94438..094164c789 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/TaskOperationType.java
@@ -15,12 +15,15 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.event;
-public class TaskExecutionContextCreateException extends MasterException {
+public enum TaskOperationType {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ FAILOVER,
+ RUN,
+ RETRY,
+ KILL,
+ PAUSE,
+ ;
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowFailedEvent.java
similarity index 69%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowFailedEvent.java
index ac37c94438..b807e726fa 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowFailedEvent.java
@@ -15,12 +15,21 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.event;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WorkflowFailedEvent implements IWorkflowEvent {
+
+ private Integer workflowInstanceId;
+
+ private String failedReason;
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowFinalizeEvent.java
similarity index 70%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowFinalizeEvent.java
index ac37c94438..0c23e15f2b 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowFinalizeEvent.java
@@ -15,12 +15,18 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.event;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class WorkflowFinalizeEvent implements IWorkflowEvent, ISyncEvent {
+ private Integer workflowInstanceId;
}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowFinalizeEventOperator.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowFinalizeEventOperator.java
new file mode 100644
index 0000000000..4c64e4c62d
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowFinalizeEventOperator.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.event;
+
+import org.apache.dolphinscheduler.workflow.engine.workflow.IWorkflowExecuteRunnableRepository;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class WorkflowFinalizeEventOperator
+ implements
+ IWorkflowEventOperator<WorkflowFinalizeEvent> {
+
+ private final IWorkflowExecuteRunnableRepository workflowExecuteRunnableRepository;
+
+ public WorkflowFinalizeEventOperator(IWorkflowExecuteRunnableRepository workflowExecuteRunnableRepository) {
+ this.workflowExecuteRunnableRepository = workflowExecuteRunnableRepository;
+ }
+
+ @Override
+ public void handleEvent(WorkflowFinalizeEvent event) {
+ Integer workflowInstanceId = event.getWorkflowInstanceId();
+ workflowExecuteRunnableRepository.removeWorkflowExecutionRunnable(workflowInstanceId);
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowFinishEvent.java
similarity index 63%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowFinishEvent.java
index ac37c94438..bd8a610599 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowFinishEvent.java
@@ -15,12 +15,23 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.event;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.common.enums.WorkflowExecutionStatus;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WorkflowFinishEvent implements IWorkflowEvent, ISyncEvent {
+
+ private Integer workflowInstanceId;
+
+ private WorkflowExecutionStatus workflowExecutionStatus;
}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowOperationEvent.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowOperationEvent.java
new file mode 100644
index 0000000000..4c7e30808f
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowOperationEvent.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.event;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+
+@Data
+@Builder
+@AllArgsConstructor
+public class WorkflowOperationEvent implements IWorkflowEvent, ISyncEvent {
+
+ private Integer workflowInstanceId;
+ private WorkflowOperationType workflowOperationType;
+
+ public static WorkflowOperationEvent of(Integer workflowInstanceId, WorkflowOperationType workflowOperationType) {
+ return WorkflowOperationEvent.builder()
+ .workflowInstanceId(workflowInstanceId)
+ .workflowOperationType(workflowOperationType)
+ .build();
+ }
+
+ public static WorkflowOperationEvent triggerEvent(Integer workflowInstanceId) {
+ return of(workflowInstanceId, WorkflowOperationType.TRIGGER);
+ }
+
+ public static WorkflowOperationEvent pauseEvent(Integer workflowInstanceId) {
+ return of(workflowInstanceId, WorkflowOperationType.PAUSE);
+ }
+
+ public static WorkflowOperationEvent killEvent(Integer workflowInstanceId) {
+ return of(workflowInstanceId, WorkflowOperationType.KILL);
+ }
+
+}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowOperationEventOperator.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowOperationEventOperator.java
new file mode 100644
index 0000000000..59a1d62e05
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowOperationEventOperator.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.event;
+
+import org.apache.dolphinscheduler.workflow.engine.utils.ExceptionUtils;
+import org.apache.dolphinscheduler.workflow.engine.workflow.IWorkflowExecuteRunnableRepository;
+import org.apache.dolphinscheduler.workflow.engine.workflow.IWorkflowExecutionContext;
+import org.apache.dolphinscheduler.workflow.engine.workflow.IWorkflowExecutionRunnable;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class WorkflowOperationEventOperator implements IWorkflowEventOperator<WorkflowOperationEvent> {
+
+ private final IWorkflowExecuteRunnableRepository workflowExecuteRunnableRepository;
+
+ public WorkflowOperationEventOperator(IWorkflowExecuteRunnableRepository workflowExecuteRunnableRepository) {
+ this.workflowExecuteRunnableRepository = workflowExecuteRunnableRepository;
+ }
+
+ @Override
+ public void handleEvent(WorkflowOperationEvent event) {
+ IWorkflowExecutionRunnable workflowExecutionRunnable =
+ workflowExecuteRunnableRepository.getWorkflowExecutionRunnableById(event.getWorkflowInstanceId());
+ if (workflowExecutionRunnable == null) {
+ log.warn("WorkflowExecutionRunnable not found: {}", event);
+ return;
+ }
+ switch (event.getWorkflowOperationType()) {
+ case TRIGGER:
+ triggerWorkflow(workflowExecutionRunnable);
+ break;
+ case PAUSE:
+ pauseWorkflow(workflowExecutionRunnable);
+ break;
+ case KILL:
+ killWorkflow(workflowExecutionRunnable);
+ break;
+ default:
+ log.error("Unknown operationType for event: {}", event);
+ }
+ }
+
+ private void triggerWorkflow(IWorkflowExecutionRunnable workflowExecutionRunnable) {
+ try {
+ workflowExecutionRunnable.start();
+ } catch (Throwable exception) {
+ if (ExceptionUtils.isDatabaseConnectedFailedException(exception)) {
+ throw exception;
+ }
+ IWorkflowExecutionContext workflowExecutionContext =
+ workflowExecutionRunnable.getWorkflowExecutionContext();
+ log.error("Trigger workflow: {} failed", workflowExecutionContext.getWorkflowInstanceName(), exception);
+ WorkflowFailedEvent workflowExecutionRunnableFailedEvent = WorkflowFailedEvent.builder()
+ .workflowInstanceId(workflowExecutionContext.getWorkflowInstanceId())
+ .failedReason(exception.getMessage())
+ .build();
+ workflowExecutionRunnable.storeEventToTail(workflowExecutionRunnableFailedEvent);
+ }
+ }
+
+ private void pauseWorkflow(IWorkflowExecutionRunnable workflowExecutionRunnable) {
+ workflowExecutionRunnable.pause();
+ }
+
+ private void killWorkflow(IWorkflowExecutionRunnable workflowExecutionRunnable) {
+ workflowExecutionRunnable.kill();
+ }
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowOperationType.java
similarity index 68%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowOperationType.java
index ac37c94438..0a1d260217 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowOperationType.java
@@ -15,12 +15,22 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.event;
-public class TaskExecutionContextCreateException extends MasterException {
+public enum WorkflowOperationType {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ /**
+ * Trigger the workflow instance.
+ */
+ TRIGGER,
+ /**
+ * Pause the workflow instance, it will pause the running task instances.
+ */
+ PAUSE,
+ /**
+ * Kill the workflow instance, it will kill the running task instances.
+ */
+ KILL,
+ ;
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/exception/WorkflowExecuteRunnableNotFoundException.java
similarity index 62%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/exception/WorkflowExecuteRunnableNotFoundException.java
index ac37c94438..10d0b4252b 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/exception/WorkflowExecuteRunnableNotFoundException.java
@@ -15,12 +15,16 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.exception;
-public class TaskExecutionContextCreateException extends MasterException {
+public class WorkflowExecuteRunnableNotFoundException extends RuntimeException {
- public TaskExecutionContextCreateException(String message) {
- super(message);
+ public WorkflowExecuteRunnableNotFoundException(Integer workflowInstanceId) {
+ super("WorkflowExecuteRunnable not found: [id=" + workflowInstanceId + "]");
+ }
+
+ public WorkflowExecuteRunnableNotFoundException(String workflowInstanceName) {
+ super("WorkflowExecuteRunnable not found: [name=" + workflowInstanceName + "]");
}
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/utils/ExceptionUtils.java
similarity index 73%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/utils/ExceptionUtils.java
index ac37c94438..625ff86e8d 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/utils/ExceptionUtils.java
@@ -15,12 +15,14 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.utils;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.springframework.dao.DataAccessResourceFailureException;
- public TaskExecutionContextCreateException(String message) {
- super(message);
+public class ExceptionUtils {
+
+ public static boolean isDatabaseConnectedFailedException(Throwable e) {
+ return e instanceof DataAccessResourceFailureException;
}
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IEventfulExecutionRunnable.java
similarity index 61%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IEventfulExecutionRunnable.java
index ac37c94438..08bfa53055 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IEventfulExecutionRunnable.java
@@ -15,12 +15,20 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.workflow;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.workflow.engine.event.IEvent;
+import org.apache.dolphinscheduler.workflow.engine.event.IEventRepository;
- public TaskExecutionContextCreateException(String message) {
- super(message);
+public interface IEventfulExecutionRunnable {
+
+ IEventRepository getEventRepository();
+
+ default void storeEventToTail(IEvent event) {
+ getEventRepository().storeEventToTail(event);
}
+ default void storeEventToHead(IEvent event) {
+ getEventRepository().storeEventToHead(event);
+ }
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/ITaskExecutionContext.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/ITaskExecutionContext.java
index ac37c94438..6a2945244c 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/ITaskExecutionContext.java
@@ -15,12 +15,10 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.workflow;
-public class TaskExecutionContextCreateException extends MasterException {
+public interface ITaskExecutionContext {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ ITaskInstance getTaskInstance();
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/ITaskExecutionContextFactory.java
similarity index 73%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/ITaskExecutionContextFactory.java
index ac37c94438..2f6a0bd9b8 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/ITaskExecutionContextFactory.java
@@ -15,12 +15,11 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.workflow;
-public class TaskExecutionContextCreateException extends MasterException {
+public interface ITaskExecutionContextFactory {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ ITaskExecutionContext createTaskExecutionContext(String taskName,
+ IWorkflowExecutionContext workflowExecutionContext);
}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/ITaskExecutionRunnable.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/ITaskExecutionRunnable.java
new file mode 100644
index 0000000000..a3ab6cc6a6
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/ITaskExecutionRunnable.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.workflow;
+
+/**
+ * The TaskExecutionRunnable represent the running task, it is responsible for operate the task instance. e.g. dispatch, kill, pause.
+ */
+public interface ITaskExecutionRunnable {
+
+ /**
+ * Dispatch the task instance.
+ */
+ void dispatch();
+
+ /**
+ * Run the task instance.
+ */
+ void run();
+
+ /**
+ * Kill the task instance.
+ */
+ void kill();
+
+ /**
+ * Pause the task instance.
+ */
+ void pause();
+
+ /**
+ * Get the task execution context.
+ *
+ * @return the task execution context
+ */
+ ITaskExecutionContext getTaskExecutionContext();
+
+ /**
+ * Determine whether the current task is ready to trigger the post task node.
+ *
+ * @param taskNodeName post task name
+ * @return true if the current task can be accessed to the post task.
+ */
+ boolean isReadyToTrigger(String taskNodeName);
+}
diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/ProcessTaskRelationLogDao.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/ITaskExecutionRunnableFactory.java
similarity index 52%
copy from dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/ProcessTaskRelationLogDao.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/ITaskExecutionRunnableFactory.java
index 8bd12026f0..b23364597b 100644
--- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/ProcessTaskRelationLogDao.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/ITaskExecutionRunnableFactory.java
@@ -15,25 +15,16 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.dao.repository;
+package org.apache.dolphinscheduler.workflow.engine.workflow;
-import org.apache.dolphinscheduler.dao.entity.ProcessTaskRelationLog;
+public interface ITaskExecutionRunnableFactory {
-import org.apache.ibatis.annotations.Param;
+ ITaskExecutionRunnable createTaskExecutionRunnable(String taskName,
+ IWorkflowExecutionContext workflowExecutionContext);
-import java.util.List;
+ ITaskExecutionRunnable createFailoverTaskExecutionRunnable(ITaskExecutionRunnable taskExecutionRunnable,
+ IWorkflowExecutionContext workflowExecutionContext);
-public interface ProcessTaskRelationLogDao extends IDao<ProcessTaskRelationLog> {
-
- List<ProcessTaskRelationLog> queryByWorkflowDefinitionCode(long workflowDefinitionCode);
-
- void deleteByWorkflowDefinitionCode(long workflowDefinitionCode);
-
- /**
- * batch insert process task relation
- *
- * @param taskRelationList taskRelationList
- * @return int
- */
- int batchInsert(@Param("taskRelationList") List<ProcessTaskRelationLog> taskRelationList);
+ ITaskExecutionRunnable createRetryTaskExecutionRunnable(ITaskExecutionRunnable taskExecutionRunnable,
+ IWorkflowExecutionContext workflowExecutionContext);
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/ITaskExecutionRunnableRepository.java
similarity index 60%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/ITaskExecutionRunnableRepository.java
index ac37c94438..d78f305665 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/ITaskExecutionRunnableRepository.java
@@ -15,12 +15,20 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.workflow;
-public class TaskExecutionContextCreateException extends MasterException {
+import java.util.Collection;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+public interface ITaskExecutionRunnableRepository {
+
+ void storeTaskExecutionRunnable(ITaskExecutionRunnable taskExecutionRunnable);
+
+ ITaskExecutionRunnable getTaskExecutionRunnableById(Integer taskInstanceId);
+
+ ITaskExecutionRunnable getTaskExecutionRunnableByName(String taskInstanceName);
+
+ Collection<ITaskExecutionRunnable> getActiveTaskExecutionRunnable();
+
+ void removeTaskExecutionRunnable(Integer taskInstanceId);
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/ITaskInstance.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/ITaskInstance.java
index ac37c94438..2e86662267 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/ITaskInstance.java
@@ -15,12 +15,12 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.workflow;
-public class TaskExecutionContextCreateException extends MasterException {
+public interface ITaskInstance {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ int getId();
+
+ String getName();
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowExecuteRunnableRepository.java
similarity index 61%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowExecuteRunnableRepository.java
index ac37c94438..758cd99a27 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowExecuteRunnableRepository.java
@@ -15,12 +15,19 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.workflow;
-public class TaskExecutionContextCreateException extends MasterException {
+import java.util.Collection;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+public interface IWorkflowExecuteRunnableRepository {
+ void storeWorkflowExecutionRunnable(IWorkflowExecutionRunnable workflowExecutionRunnable);
+
+ IWorkflowExecutionRunnable getWorkflowExecutionRunnableById(Integer workflowInstanceId);
+
+ Collection<IWorkflowExecutionRunnable> getActiveWorkflowExecutionRunnable();
+
+ void removeWorkflowExecutionRunnable(Integer workflowInstanceId);
+
+ void clear();
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowExecutionContext.java
similarity index 61%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowExecutionContext.java
index ac37c94438..265076b4f1 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowExecutionContext.java
@@ -15,12 +15,24 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.workflow;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.workflow.engine.event.IEventRepository;
- public TaskExecutionContextCreateException(String message) {
- super(message);
+public interface IWorkflowExecutionContext {
+
+ IWorkflowInstance getWorkflowInstance();
+
+ IWorkflowExecutionDAG getWorkflowExecutionDAG();
+
+ IEventRepository getEventRepository();
+
+ default int getWorkflowInstanceId() {
+ return getWorkflowInstance().getId();
+ }
+
+ default String getWorkflowInstanceName() {
+ return getWorkflowInstance().getName();
}
}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowExecutionDAG.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowExecutionDAG.java
new file mode 100644
index 0000000000..d76ee1a64a
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowExecutionDAG.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.workflow;
+
+import org.apache.dolphinscheduler.workflow.engine.dag.DAG;
+
+import java.util.List;
+
+/**
+ * The WorkflowExecutionDAG represent the running workflow DAG.
+ */
+public interface IWorkflowExecutionDAG extends DAG {
+
+ List<String> getStartNodeNames();
+
+ /**
+ * Get TaskExecutionRunnable by given TaskInstanceId.
+ *
+ * @param taskInstanceId taskInstanceId.
+ * @return TaskExecutionRunnable
+ */
+ ITaskExecutionRunnable getTaskExecutionRunnableById(Integer taskInstanceId);
+
+ /**
+ * Get TaskExecutionRunnable by given taskName.
+ *
+ * @param taskName task name.
+ * @return TaskExecutionRunnable
+ */
+ ITaskExecutionRunnable getTaskExecutionRunnableByName(String taskName);
+
+ /**
+ * Get TaskExecutionRunnable which is not finished.
+ *
+ * @return TaskExecutionRunnable
+ */
+ List<ITaskExecutionRunnable> getActiveTaskExecutionRunnable();
+
+ /**
+ * Get the direct pre TaskExecutionRunnable of the given taskName.
+ *
+ * @param taskName task name.
+ * @return TaskExecutionRunnable
+ */
+ List<ITaskExecutionRunnable> getDirectPreTaskExecutionRunnable(String taskName);
+
+ /**
+ * Check whether the taskNode is ready to run.
+ *
+ * @param taskName taskNodeName
+ * @return true if the taskNode is ready to run.
+ */
+ boolean isTaskAbleToBeTriggered(String taskName);
+
+ void storeTaskExecutionRunnable(ITaskExecutionRunnable taskExecutionRunnable);
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowExecutionDAGFactory.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowExecutionDAGFactory.java
index ac37c94438..dbac2888f4 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowExecutionDAGFactory.java
@@ -15,12 +15,10 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.workflow;
-public class TaskExecutionContextCreateException extends MasterException {
+public interface IWorkflowExecutionDAGFactory {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ IWorkflowExecutionDAG createWorkflowExecutionDAG(IWorkflowExecutionContext workflowExecutionContext);
}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowExecutionRunnable.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowExecutionRunnable.java
new file mode 100644
index 0000000000..1c6e75ba1e
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowExecutionRunnable.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.workflow;
+
+import org.apache.dolphinscheduler.workflow.engine.engine.IDAGEngine;
+
+/**
+ * The IWorkflowExecuteRunnable represent a running workflow instance, it is responsible for operate the workflow instance. e.g. start, kill, pause.
+ */
+public interface IWorkflowExecutionRunnable extends IEventfulExecutionRunnable {
+
+ /**
+ * Start the workflow instance.
+ */
+ void start();
+
+ /**
+ * Kill the workflow instance.
+ */
+ void kill();
+
+ /**
+ * Pause the workflow instance.
+ */
+ void pause();
+
+ /**
+ * Get the workflow execution context.
+ *
+ * @return the workflow execution context
+ */
+ IWorkflowExecutionContext getWorkflowExecutionContext();
+
+ /**
+ * Get the {@link IDAGEngine} which used to execute the dag of the workflow instance.
+ *
+ * @return dag engine.
+ */
+ IDAGEngine getDagEngine();
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowExecutionRunnableFactory.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowExecutionRunnableFactory.java
index ac37c94438..f2c5042e4f 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowExecutionRunnableFactory.java
@@ -15,12 +15,10 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.workflow;
-public class TaskExecutionContextCreateException extends MasterException {
+public interface IWorkflowExecutionRunnableFactory {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ IWorkflowExecutionRunnable createWorkflowExecutionRunnable(IWorkflowExecutionContext workflowExecutionContext);
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowInstance.java
similarity index 77%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowInstance.java
index ac37c94438..49944d248a 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/IWorkflowInstance.java
@@ -15,12 +15,12 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.workflow;
-public class TaskExecutionContextCreateException extends MasterException {
+public interface IWorkflowInstance {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ int getId();
+
+ String getName();
}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/SingletonWorkflowExecuteRunnableRepository.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/SingletonWorkflowExecuteRunnableRepository.java
new file mode 100644
index 0000000000..147f0076ba
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/SingletonWorkflowExecuteRunnableRepository.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.workflow;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class SingletonWorkflowExecuteRunnableRepository implements IWorkflowExecuteRunnableRepository {
+
+ private static final IWorkflowExecuteRunnableRepository INSTANCE = new SingletonWorkflowExecuteRunnableRepository();
+
+ private final Map<Integer, IWorkflowExecutionRunnable> workflowExecutionRunnableMap;
+
+ private SingletonWorkflowExecuteRunnableRepository() {
+ this.workflowExecutionRunnableMap = new ConcurrentHashMap<>();
+ }
+
+ public static IWorkflowExecuteRunnableRepository getInstance() {
+ return INSTANCE;
+ }
+
+ public void storeWorkflowExecutionRunnable(IWorkflowExecutionRunnable workflowExecutionRunnable) {
+ workflowExecutionRunnableMap.put(
+ workflowExecutionRunnable.getWorkflowExecutionContext().getWorkflowInstanceId(),
+ workflowExecutionRunnable);
+ }
+
+ public IWorkflowExecutionRunnable getWorkflowExecutionRunnableById(Integer workflowInstanceId) {
+ return workflowExecutionRunnableMap.get(workflowInstanceId);
+ }
+
+ public Collection<IWorkflowExecutionRunnable> getActiveWorkflowExecutionRunnable() {
+ return workflowExecutionRunnableMap.values();
+ }
+
+ public void removeWorkflowExecutionRunnable(Integer workflowInstanceId) {
+ workflowExecutionRunnableMap.remove(workflowInstanceId);
+ }
+
+ @Override
+ public void clear() {
+ workflowExecutionRunnableMap.clear();
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/TaskExecutionContext.java
similarity index 68%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/TaskExecutionContext.java
index ac37c94438..380ed8b1ee 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/TaskExecutionContext.java
@@ -15,12 +15,18 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.workflow;
-public class TaskExecutionContextCreateException extends MasterException {
+public class TaskExecutionContext implements ITaskExecutionContext {
- public TaskExecutionContextCreateException(String message) {
- super(message);
+ private final ITaskInstance taskInstance;
+
+ public TaskExecutionContext(ITaskInstance taskInstance) {
+ this.taskInstance = taskInstance;
}
+ @Override
+ public ITaskInstance getTaskInstance() {
+ return taskInstance;
+ }
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/TaskExecutionContextFactory.java
similarity index 68%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/TaskExecutionContextFactory.java
index ac37c94438..446bb2f661 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/TaskExecutionContextFactory.java
@@ -15,12 +15,13 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.workflow;
-public class TaskExecutionContextCreateException extends MasterException {
+public class TaskExecutionContextFactory implements ITaskExecutionContextFactory {
- public TaskExecutionContextCreateException(String message) {
- super(message);
+ @Override
+ public ITaskExecutionContext createTaskExecutionContext(String taskName,
+ IWorkflowExecutionContext workflowExecutionContext) {
+ return null;
}
-
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/TaskExecutionRunnable.java
similarity index 52%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/TaskExecutionRunnable.java
index ac37c94438..322cd8ee8d 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/TaskExecutionRunnable.java
@@ -15,12 +15,43 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.workflow;
-public class TaskExecutionContextCreateException extends MasterException {
+public class TaskExecutionRunnable implements ITaskExecutionRunnable {
- public TaskExecutionContextCreateException(String message) {
- super(message);
+ public final ITaskExecutionContext taskExecutionContext;
+
+ public TaskExecutionRunnable(ITaskExecutionContext taskExecutionContext) {
+ this.taskExecutionContext = taskExecutionContext;
+ }
+
+ @Override
+ public void dispatch() {
+
+ }
+
+ @Override
+ public void run() {
+
+ }
+
+ @Override
+ public void kill() {
+
+ }
+
+ @Override
+ public void pause() {
+
+ }
+
+ @Override
+ public ITaskExecutionContext getTaskExecutionContext() {
+ return taskExecutionContext;
}
+ @Override
+ public boolean isReadyToTrigger(String taskNodeName) {
+ return false;
+ }
}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/TaskExecutionRunnableFactory.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/TaskExecutionRunnableFactory.java
new file mode 100644
index 0000000000..3e7b5ec7c2
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/TaskExecutionRunnableFactory.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.workflow;
+
+public class TaskExecutionRunnableFactory implements ITaskExecutionRunnableFactory {
+
+ private ITaskExecutionContextFactory taskExecutionContextFactory;
+
+ public TaskExecutionRunnableFactory(ITaskExecutionContextFactory taskExecutionContextFactory) {
+ this.taskExecutionContextFactory = taskExecutionContextFactory;
+ }
+
+ @Override
+ public ITaskExecutionRunnable createTaskExecutionRunnable(String taskName,
+ IWorkflowExecutionContext workflowExecutionContext) {
+ ITaskExecutionContext taskExecutionContext =
+ taskExecutionContextFactory.createTaskExecutionContext(taskName, workflowExecutionContext);
+ return new TaskExecutionRunnable(taskExecutionContext);
+ }
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/WorkflowExecutionContext.java
similarity index 60%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/WorkflowExecutionContext.java
index ac37c94438..6cca1eced1 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/WorkflowExecutionContext.java
@@ -15,12 +15,25 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.workflow;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.workflow.engine.event.IEventRepository;
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class WorkflowExecutionContext implements IWorkflowExecutionContext {
+
+ private IWorkflowInstance workflowInstance;
+
+ private IWorkflowExecutionDAG workflowExecutionDAG;
+
+ private IEventRepository eventRepository;
}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/WorkflowExecutionDAG.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/WorkflowExecutionDAG.java
new file mode 100644
index 0000000000..01fafcc6b7
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/WorkflowExecutionDAG.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.workflow;
+
+import org.apache.dolphinscheduler.workflow.engine.dag.DAGNode;
+import org.apache.dolphinscheduler.workflow.engine.dag.WorkflowDAG;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * The WorkflowExecutionDAG represent a running workflow instance DAG.
+ */
+@Slf4j
+public class WorkflowExecutionDAG implements IWorkflowExecutionDAG {
+
+ private final ITaskExecutionRunnableRepository taskExecutionRunnableRepository;
+
+ private final WorkflowDAG workflowDAG;
+
+ @Getter
+ private final Set<String> startNodeNames;
+
+ public WorkflowExecutionDAG(ITaskExecutionRunnableRepository taskExecutionRunnableRepository,
+ WorkflowDAG workflowDAG) {
+ this(taskExecutionRunnableRepository, workflowDAG, Collections.emptySet());
+ }
+
+ public WorkflowExecutionDAG(ITaskExecutionRunnableRepository taskExecutionRunnableRepository,
+ WorkflowDAG workflowDAG,
+ Set<String> startNodeNames) {
+ this.taskExecutionRunnableRepository = taskExecutionRunnableRepository;
+ this.workflowDAG = workflowDAG;
+ this.startNodeNames = startNodeNames;
+ }
+
+ @Override
+ public ITaskExecutionRunnable getTaskExecutionRunnableById(Integer taskInstanceId) {
+ return taskExecutionRunnableRepository.getTaskExecutionRunnableById(taskInstanceId);
+ }
+
+ @Override
+ public ITaskExecutionRunnable getTaskExecutionRunnableByName(String taskName) {
+ return taskExecutionRunnableRepository.getTaskExecutionRunnableByName(taskName);
+ }
+
+ @Override
+ public List<ITaskExecutionRunnable> getActiveTaskExecutionRunnable() {
+ return new ArrayList<>(taskExecutionRunnableRepository.getActiveTaskExecutionRunnable());
+ }
+
+ @Override
+ public List<ITaskExecutionRunnable> getDirectPreTaskExecutionRunnable(String taskName) {
+ return getDirectPreNodeNames(taskName)
+ .stream()
+ .map(taskExecutionRunnableRepository::getTaskExecutionRunnableByName)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public boolean isTaskAbleToBeTriggered(String taskNodeName) {
+ // todo: Check whether the workflow instance is finished or ready to finish.
+ List<DAGNode> directPreNodes = getDirectPreNodes(taskNodeName);
+ if (log.isDebugEnabled()) {
+ log.debug("Begin to check whether the task {} is able to be triggered.", taskNodeName);
+ log.debug("Task {} directly dependent on the task: {}.", taskNodeName,
+ directPreNodes.stream().map(DAGNode::getNodeName).collect(Collectors.toList()));
+ }
+ for (DAGNode directPreNode : directPreNodes) {
+ if (directPreNode.isSkip()) {
+ log.debug("The task {} is skipped.", directPreNode.getNodeName());
+ continue;
+ }
+ ITaskExecutionRunnable taskExecutionRunnable = getTaskExecutionRunnableByName(directPreNode.getNodeName());
+ if (taskExecutionRunnable == null || taskExecutionRunnable.isReadyToTrigger(taskNodeName)) {
+ log.debug("The task {} is not finished or not able to access to the task {}.",
+ directPreNode.getNodeName(), taskNodeName);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void storeTaskExecutionRunnable(ITaskExecutionRunnable taskExecutionRunnable) {
+ taskExecutionRunnableRepository.storeTaskExecutionRunnable(taskExecutionRunnable);
+ }
+
+ @Override
+ public List<DAGNode> getDirectPostNodes(DAGNode dagNode) {
+ return workflowDAG.getDirectPostNodes(dagNode);
+ }
+
+ @Override
+ public List<DAGNode> getDirectPreNodes(DAGNode dagNode) {
+ return workflowDAG.getDirectPreNodes(dagNode);
+ }
+
+ @Override
+ public DAGNode getDAGNode(String nodeName) {
+ return workflowDAG.getDAGNode(nodeName);
+ }
+
+}
diff --git a/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/WorkflowExecutionRunnable.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/WorkflowExecutionRunnable.java
new file mode 100644
index 0000000000..7b05d22048
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/WorkflowExecutionRunnable.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.workflow;
+
+import org.apache.dolphinscheduler.workflow.engine.engine.IDAGEngine;
+import org.apache.dolphinscheduler.workflow.engine.event.IEventRepository;
+
+import org.apache.commons.collections4.CollectionUtils;
+
+import java.util.List;
+
+import lombok.Getter;
+
+@Getter
+public class WorkflowExecutionRunnable implements IWorkflowExecutionRunnable {
+
+ private final IWorkflowExecutionContext workflowExecutionContext;
+
+ private final IDAGEngine dagEngine;
+
+ public WorkflowExecutionRunnable(IWorkflowExecutionContext workflowExecutionContext, IDAGEngine dagEngine) {
+ this.workflowExecutionContext = workflowExecutionContext;
+ this.dagEngine = dagEngine;
+ }
+
+ public void start() {
+ List<String> workflowStartNodeNames = workflowExecutionContext.getWorkflowExecutionDAG().getStartNodeNames();
+ if (CollectionUtils.isEmpty(workflowStartNodeNames)) {
+ dagEngine.triggerNextTasks(null);
+ } else {
+ workflowStartNodeNames.forEach(dagEngine::triggerTask);
+ }
+ }
+
+ @Override
+ public void pause() {
+ dagEngine.pauseAllTask();
+ }
+
+ @Override
+ public void kill() {
+ dagEngine.killAllTask();
+ }
+
+ @Override
+ public IEventRepository getEventRepository() {
+ return workflowExecutionContext.getEventRepository();
+ }
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/WorkflowExecutionRunnableFactory.java
similarity index 50%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/WorkflowExecutionRunnableFactory.java
index ac37c94438..ebfb3510db 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/WorkflowExecutionRunnableFactory.java
@@ -15,12 +15,22 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.workflow;
-public class TaskExecutionContextCreateException extends MasterException {
+import org.apache.dolphinscheduler.workflow.engine.engine.IDAGEngine;
+import org.apache.dolphinscheduler.workflow.engine.engine.IDAGEngineFactory;
- public TaskExecutionContextCreateException(String message) {
- super(message);
+public class WorkflowExecutionRunnableFactory implements IWorkflowExecutionRunnableFactory {
+
+ private final IDAGEngineFactory dagEngineFactory;
+
+ public WorkflowExecutionRunnableFactory(IDAGEngineFactory dagEngineFactory) {
+ this.dagEngineFactory = dagEngineFactory;
}
+ @Override
+ public WorkflowExecutionRunnable createWorkflowExecutionRunnable(IWorkflowExecutionContext workflowExecutionContext) {
+ IDAGEngine dagEngine = dagEngineFactory.createDAGEngine(workflowExecutionContext);
+ return new WorkflowExecutionRunnable(workflowExecutionContext, dagEngine);
+ }
}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/WorkflowInstance.java
similarity index 65%
copy from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
copy to dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/WorkflowInstance.java
index ac37c94438..5280e86c08 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/main/java/org/apache/dolphinscheduler/workflow/engine/workflow/WorkflowInstance.java
@@ -15,12 +15,24 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.workflow;
-public class TaskExecutionContextCreateException extends MasterException {
+import lombok.Getter;
- public TaskExecutionContextCreateException(String message) {
- super(message);
+@Getter
+public class WorkflowInstance implements IWorkflowInstance {
+
+ private final int id;
+
+ private final String name;
+
+ public WorkflowInstance(int id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public static WorkflowInstance of(int id, String name) {
+ return new WorkflowInstance(id, name);
}
}
diff --git a/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/assertions/SingletonWorkflowExecuteRunnableRepositoryAssertions.java b/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/assertions/SingletonWorkflowExecuteRunnableRepositoryAssertions.java
new file mode 100644
index 0000000000..1d4553d2a7
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/assertions/SingletonWorkflowExecuteRunnableRepositoryAssertions.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.assertions;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import org.apache.dolphinscheduler.workflow.engine.workflow.SingletonWorkflowExecuteRunnableRepository;
+
+public class SingletonWorkflowExecuteRunnableRepositoryAssertions {
+
+ public static void existWorkflowExecutionRunnable(Integer workflowInstanceId) {
+ assertNotNull(SingletonWorkflowExecuteRunnableRepository.getInstance()
+ .getWorkflowExecutionRunnableById(workflowInstanceId));
+ }
+
+ public static void notExistWorkflowExecutionRunnable(Integer workflowInstanceId) {
+ assertNull(SingletonWorkflowExecuteRunnableRepository.getInstance()
+ .getWorkflowExecutionRunnableById(workflowInstanceId));
+ }
+
+}
diff --git a/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/assertions/WorkflowDAGAssertion.java b/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/assertions/WorkflowDAGAssertion.java
new file mode 100644
index 0000000000..3ccbc4702a
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/assertions/WorkflowDAGAssertion.java
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.assertions;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.dolphinscheduler.workflow.engine.dag.WorkflowDAG;
+
+import org.apache.commons.collections4.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class WorkflowDAGAssertion {
+
+ private final WorkflowDAG workflowDAG;
+
+ private final List<NodeAssertion> nodeAssertions;
+
+ private WorkflowDAGAssertion(WorkflowDAG workflowDAG) {
+ this.workflowDAG = workflowDAG;
+ this.nodeAssertions = new ArrayList<>();
+ }
+
+ public static WorkflowDAGAssertion workflowDag(WorkflowDAG workflowDAG) {
+ return new WorkflowDAGAssertion(workflowDAG);
+ }
+
+ public WorkflowDAGAssertion nodeAssertion(NodeAssertion nodeAssertion) {
+ nodeAssertions.add(nodeAssertion);
+ return this;
+ }
+
+ public void doAssertion() {
+ nodeAssertions.forEach(nodeAssertion -> nodeAssertion.doAssertion(workflowDAG));
+ }
+
+ public static class NodeAssertion {
+
+ /**
+ * node name of the assertion
+ */
+ private final String nodeName;
+
+ /**
+ * whether the node exist
+ */
+ private boolean exist;
+
+ /**
+ * whether the node is skipped
+ */
+ private boolean skip;
+
+ /**
+ * whether the node has out degree
+ */
+ private List<String> postNodes;
+
+ /**
+ * whether the node has in degree
+ */
+ private List<String> preNodes;
+
+ private NodeAssertion(String nodeName) {
+ this.nodeName = nodeName;
+ this.postNodes = new ArrayList<>();
+ this.preNodes = new ArrayList<>();
+ }
+
+ public static NodeAssertion node(String nodeName) {
+ return new NodeAssertion(nodeName);
+ }
+
+ public NodeAssertion exist() {
+ this.exist = true;
+ return this;
+ }
+
+ public NodeAssertion skip() {
+ this.skip = true;
+ return this;
+ }
+
+ public NodeAssertion noEdge() {
+ this.postNodes = new ArrayList<>();
+ this.preNodes = new ArrayList<>();
+ return this;
+ }
+
+ public NodeAssertion noInDegree() {
+ this.preNodes = new ArrayList<>();
+ return this;
+ }
+
+ public NodeAssertion inDegrees(List<String> preNodes) {
+ this.preNodes.addAll(preNodes);
+ return this;
+ }
+
+ public NodeAssertion inDegrees(String preNode) {
+ this.preNodes.add(preNode);
+ return this;
+ }
+
+ public NodeAssertion noOutDegree() {
+ this.postNodes = new ArrayList<>();
+ return this;
+ }
+
+ public NodeAssertion outDegrees(List<String> postNodes) {
+ this.postNodes.addAll(postNodes);
+ return this;
+ }
+
+ public NodeAssertion outDegrees(String postNode) {
+ this.postNodes.add(postNode);
+ return this;
+ }
+
+ private void doAssertion(WorkflowDAG workflowDAG) {
+ if (exist) {
+ // node exist
+ assertNotNull(workflowDAG.getDAGNode(nodeName), "node " + nodeName + " does not exist");
+ } else {
+
+ assertNull(workflowDAG.getDAGNode(nodeName), "node " + nodeName + " exist");
+ }
+
+ if (skip) {
+ assertTrue(workflowDAG.getDAGNode(nodeName).isSkip(), "node " + nodeName + " is not skipped");
+ } else {
+ assertFalse(workflowDAG.getDAGNode(nodeName).isSkip(), "node " + nodeName + " is skipped");
+ }
+
+ if (CollectionUtils.isEmpty(postNodes)) {
+ assertTrue(workflowDAG.getDirectPostNodeNames(nodeName).isEmpty(),
+ "node " + nodeName + " has outDegree " + workflowDAG.getDirectPostNodes(nodeName));
+ } else {
+ postNodes
+ .forEach(postNode -> assertTrue(workflowDAG.getDirectPostNodeNames(nodeName).contains(postNode),
+ "node " + nodeName + " does has outDegree " + postNode));
+ }
+
+ if (CollectionUtils.isEmpty(preNodes)) {
+ assertTrue(workflowDAG.getDirectPreNodeNames(nodeName).isEmpty(),
+ "node " + nodeName + " has inDegree " + workflowDAG.getDirectPreNodeNames(nodeName));
+ } else {
+ preNodes.forEach(preNode -> assertTrue(workflowDAG.getDirectPreNodeNames(nodeName).contains(preNode),
+ "node " + nodeName + " does has inDegree " + preNode));
+ }
+ }
+ }
+
+}
diff --git a/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/assertions/WorkflowExecutionRunnableAssertions.java b/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/assertions/WorkflowExecutionRunnableAssertions.java
new file mode 100644
index 0000000000..494e66bcd6
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/assertions/WorkflowExecutionRunnableAssertions.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.assertions;
+
+import org.apache.dolphinscheduler.workflow.engine.event.IEvent;
+import org.apache.dolphinscheduler.workflow.engine.workflow.IWorkflowExecutionRunnable;
+
+import org.opentest4j.AssertionFailedError;
+
+public class WorkflowExecutionRunnableAssertions {
+
+ private final IWorkflowExecutionRunnable workflowExecutionRunnable;
+
+ private WorkflowExecutionRunnableAssertions(IWorkflowExecutionRunnable workflowExecutionRunnable) {
+ this.workflowExecutionRunnable = workflowExecutionRunnable;
+ }
+
+ public static WorkflowExecutionRunnableAssertions workflowExecutionRunnable(IWorkflowExecutionRunnable workflowExecutionRunnable) {
+ return new WorkflowExecutionRunnableAssertions(workflowExecutionRunnable);
+ }
+
+ public void existEvent(IEvent event) {
+ if (event == null) {
+ throw new IllegalArgumentException("Event cannot be null");
+ }
+ boolean exist = workflowExecutionRunnable.getEventRepository().getAllEvent()
+ .stream()
+ .anyMatch(event1 -> event1.equals(event1));
+ if (!exist) {
+ throw new AssertionFailedError("The workflowExecuteRunnable doesn't exist event: " + event);
+ }
+ }
+
+}
diff --git a/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/dag/DAGNodeTest.java b/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/dag/DAGNodeTest.java
new file mode 100644
index 0000000000..0502450f82
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/dag/DAGNodeTest.java
@@ -0,0 +1,104 @@
+package org.apache.dolphinscheduler.workflow.engine.dag;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+
+import org.junit.jupiter.api.Test;
+
+import com.google.common.collect.Lists;
+
+class DAGNodeTest {
+
+ @Test
+ void buildDAGNode_EmptyNodeName() {
+ IllegalArgumentException illegalArgumentException = assertThrows(IllegalArgumentException.class,
+ () -> DAGNode.builder()
+ .inDegrees(new ArrayList<>())
+ .outDegrees(new ArrayList<>())
+ .build());
+ assertEquals("nodeName cannot be empty", illegalArgumentException.getMessage());
+ }
+
+ @Test
+ void buildDAGNode_BadInDegree() {
+ IllegalArgumentException illegalArgumentException = assertThrows(IllegalArgumentException.class,
+ () -> DAGNode.builder()
+ .nodeName("A")
+ .inDegrees(Lists.newArrayList(DAGEdge.builder()
+ .fromNodeName(null)
+ .toNodeName("B")
+ .build()))
+ .outDegrees(new ArrayList<>())
+ .build());
+ assertEquals(
+ "The toNodeName of inDegree should be the nodeName of the node: A, inDegree: DAGEdge(fromNodeName=null, toNodeName=B)",
+ illegalArgumentException.getMessage());
+ }
+
+ @Test
+ void buildDAGNode_NiceInDegree() {
+ assertDoesNotThrow(() -> DAGNode.builder()
+ .nodeName("A")
+ .inDegrees(Lists.newArrayList(DAGEdge.builder()
+ .fromNodeName(null)
+ .toNodeName("A")
+ .build()))
+ .outDegrees(new ArrayList<>())
+ .build());
+ }
+
+ @Test
+ void buildDAGNode_BadOutDegree() {
+ IllegalArgumentException illegalArgumentException = assertThrows(IllegalArgumentException.class,
+ () -> DAGNode.builder()
+ .nodeName("A")
+ .inDegrees(new ArrayList<>())
+ .outDegrees(Lists.newArrayList(DAGEdge.builder()
+ .fromNodeName("B")
+ .toNodeName(null)
+ .build()))
+ .build());
+ assertEquals(
+ "The fromNodeName of outDegree should be the nodeName of the node: A, outDegree: DAGEdge(fromNodeName=B, toNodeName=null)",
+ illegalArgumentException.getMessage());
+ }
+
+ @Test
+ void buildDAGNode_NiceOutDegree() {
+ assertDoesNotThrow(() -> DAGNode.builder()
+ .nodeName("A")
+ .inDegrees(new ArrayList<>())
+ .outDegrees(Lists.newArrayList(DAGEdge.builder()
+ .fromNodeName("A")
+ .toNodeName(null)
+ .build()))
+ .build());
+ }
+
+ @Test
+ void buildDAGNode_NotSkip() {
+ DAGNode dagNode = DAGNode.builder()
+ .nodeName("A")
+ .inDegrees(new ArrayList<>())
+ .outDegrees(new ArrayList<>())
+ .build();
+ assertFalse(dagNode.isSkip());
+ }
+
+ @Test
+ void buildDAGNode_Skip() {
+ DAGNode dagNode = DAGNode.builder()
+ .nodeName("A")
+ .skip(true)
+ .inDegrees(new ArrayList<>())
+ .outDegrees(new ArrayList<>())
+ .build();
+ assertTrue(dagNode.isSkip());
+ }
+
+}
diff --git a/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/dag/WorkflowDAGBuilderTest.java b/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/dag/WorkflowDAGBuilderTest.java
new file mode 100644
index 0000000000..e37a73f32a
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/dag/WorkflowDAGBuilderTest.java
@@ -0,0 +1,260 @@
+package org.apache.dolphinscheduler.workflow.engine.dag;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.apache.dolphinscheduler.workflow.engine.assertions.WorkflowDAGAssertion.NodeAssertion.node;
+import static org.apache.dolphinscheduler.workflow.engine.assertions.WorkflowDAGAssertion.workflowDag;
+
+import org.junit.jupiter.api.Test;
+
+class WorkflowDAGBuilderTest {
+
+ /**
+ * Test DAG with single node:
+ * <pre>
+ * {@code
+ * Node(A)
+ * }
+ * </pre>
+ */
+ @Test
+ void build_SingleTaskNode() {
+ String nodeName = "A";
+ DAGNodeDefinition dagNodeDefinition = dagNode(nodeName);
+ WorkflowDAG workflowDAG = WorkflowDAGBuilder.newBuilder()
+ .addTaskNode(dagNodeDefinition)
+ .build();
+ workflowDag(workflowDAG)
+ .nodeAssertion(node(nodeName).exist().noEdge())
+ .doAssertion();
+ }
+
+ /**
+ * Test DAG with multiple nodes:
+ * <pre>
+ * {@code
+ * Node(A)
+ * Node(B)
+ * Node(C)
+ * }
+ * <pre/>
+ */
+ @Test
+ void build_MULTIPLE_NODE() {
+ String nodeNameA = "A";
+ DAGNodeDefinition taskNodeA = dagNode(nodeNameA);
+ String nodeNameB = "B";
+ DAGNodeDefinition taskNodeB = dagNode(nodeNameB);
+ String nodeNameC = "C";
+ DAGNodeDefinition taskNodeC = dagNode(nodeNameC);
+
+ WorkflowDAG workflowDAG = WorkflowDAGBuilder.newBuilder()
+ .addTaskNode(taskNodeA)
+ .addTaskNode(taskNodeB)
+ .addTaskNode(taskNodeC)
+ .build();
+ workflowDag(workflowDAG)
+ .nodeAssertion(node(nodeNameA).exist().noEdge())
+ .nodeAssertion(node(nodeNameB).exist().noEdge())
+ .nodeAssertion(node(nodeNameC).exist().noEdge())
+ .doAssertion();
+ }
+
+ /**
+ * Test DAG with multiple nodes:
+ * <pre>
+ * {@code
+ * Node(A) -> Node(B1) -> Node(C1) -> Node(D)
+ * -> Node(B2) -> Node(C2) ->
+ * }
+ * <pre/>
+ */
+ @Test
+ void build_DAG() {
+ String nodeNameA = "A";
+ DAGNodeDefinition taskNodeA = dagNode(nodeNameA);
+ String nodeNameB1 = "B1";
+ DAGNodeDefinition taskNodeB1 = dagNode(nodeNameB1);
+ String nodeNameB2 = "B2";
+ DAGNodeDefinition taskNodeB2 = dagNode(nodeNameB2);
+ String nodeNameC1 = "C1";
+ DAGNodeDefinition taskNodeC1 = dagNode(nodeNameC1);
+ String nodeNameC2 = "C2";
+ DAGNodeDefinition taskNodeC2 = dagNode(nodeNameC2);
+ String nodeNameD = "D";
+ DAGNodeDefinition taskNodeD = dagNode(nodeNameD);
+
+ WorkflowDAG workflowDAG = WorkflowDAGBuilder.newBuilder()
+ .addTaskNode(taskNodeA)
+ .addTaskNodes(newArrayList(taskNodeB1, taskNodeB2))
+ .addTaskNodes(newArrayList(taskNodeC1, taskNodeC2))
+ .addTaskNode(taskNodeD)
+ .addTaskEdge(edge(null, taskNodeA))
+ .addTaskEdge(edge(taskNodeA, taskNodeB1))
+ .addTaskEdge(edge(taskNodeA, taskNodeB2))
+ .addTaskEdge(edge(taskNodeB1, taskNodeC1))
+ .addTaskEdge(edge(taskNodeB2, taskNodeC2))
+ .addTaskEdge(edge(taskNodeC1, taskNodeD))
+ .addTaskEdge(edge(taskNodeC2, taskNodeD))
+ .addTaskEdge(edge(taskNodeD, null))
+ .build();
+ workflowDag(workflowDAG)
+ .nodeAssertion(node(nodeNameA)
+ .exist()
+ .noInDegree()
+ .outDegrees(newArrayList(nodeNameB1, nodeNameB2)))
+ .nodeAssertion(node(nodeNameB1)
+ .exist()
+ .inDegrees(nodeNameA)
+ .outDegrees(nodeNameC1))
+ .nodeAssertion(node(nodeNameB2)
+ .exist()
+ .inDegrees(nodeNameA)
+ .outDegrees(nodeNameC2))
+ .nodeAssertion(node(nodeNameC1)
+ .exist()
+ .inDegrees(nodeNameB1)
+ .outDegrees(nodeNameD))
+ .nodeAssertion(node(nodeNameC2)
+ .exist()
+ .inDegrees(nodeNameB2)
+ .outDegrees(nodeNameD))
+ .nodeAssertion(node(nodeNameD)
+ .exist()
+ .inDegrees(newArrayList(nodeNameC1, nodeNameC2))
+ .noOutDegree())
+ .doAssertion();
+ }
+
+ /**
+ * Test DAG with multiple sub dags:
+ * <pre>
+ * {@code
+ * Node(A1) -> Node(B1) -> Node(C1) -> Node(D1)
+ * -> Node(B2) -> Node(C2) ->
+ *
+ * Node(A2) -> Node(B3) -> Node(C3) -> Node(D2)
+ * -> Node(B4) -> Node(C4) ->
+ * }
+ * <pre/>
+ */
+ @Test
+ void build_MULTIPLE_SUB_DAG() {
+ String nodeNameA1 = "A1";
+ DAGNodeDefinition taskNodeA1 = dagNode(nodeNameA1);
+ String nodeNameA2 = "A2";
+ DAGNodeDefinition taskNodeA2 = dagNode(nodeNameA2);
+
+ String nodeNameB1 = "B1";
+ DAGNodeDefinition taskNodeB1 = dagNode(nodeNameB1);
+ String nodeNameB2 = "B2";
+ DAGNodeDefinition taskNodeB2 = dagNode(nodeNameB2);
+ String nodeNameB3 = "B3";
+ DAGNodeDefinition taskNodeB3 = dagNode(nodeNameB3);
+ String nodeNameB4 = "B4";
+ DAGNodeDefinition taskNodeB4 = dagNode(nodeNameB4);
+
+ String nodeNameC1 = "C1";
+ DAGNodeDefinition taskNodeC1 = dagNode(nodeNameC1);
+ String nodeNameC2 = "C2";
+ DAGNodeDefinition taskNodeC2 = dagNode(nodeNameC2);
+ String nodeNameC3 = "C3";
+ DAGNodeDefinition taskNodeC3 = dagNode(nodeNameC3);
+ String nodeNameC4 = "C4";
+ DAGNodeDefinition taskNodeC4 = dagNode(nodeNameC4);
+
+ String nodeNameD1 = "D1";
+ DAGNodeDefinition taskNodeD1 = dagNode(nodeNameD1);
+ String nodeNameD2 = "D2";
+ DAGNodeDefinition taskNodeD2 = dagNode(nodeNameD2);
+
+ WorkflowDAG workflowDAG = WorkflowDAGBuilder.newBuilder()
+ .addTaskNodes(newArrayList(taskNodeA1, taskNodeA2))
+ .addTaskNodes(newArrayList(taskNodeB1, taskNodeB2, taskNodeB3, taskNodeB4))
+ .addTaskNodes(newArrayList(taskNodeC1, taskNodeC2, taskNodeC3, taskNodeC4))
+ .addTaskNodes(newArrayList(taskNodeD1, taskNodeD2))
+ .addTaskEdge(edge(null, taskNodeA1))
+ .addTaskEdge(edge(taskNodeA1, taskNodeB1))
+ .addTaskEdge(edge(taskNodeA1, taskNodeB2))
+ .addTaskEdge(edge(taskNodeB1, taskNodeC1))
+ .addTaskEdge(edge(taskNodeB2, taskNodeC2))
+ .addTaskEdge(edge(taskNodeC1, taskNodeD1))
+ .addTaskEdge(edge(taskNodeC2, taskNodeD1))
+ .addTaskEdge(edge(taskNodeD1, null))
+ .addTaskEdge(edge(null, taskNodeA2))
+ .addTaskEdge(edge(taskNodeA2, taskNodeB3))
+ .addTaskEdge(edge(taskNodeA2, taskNodeB4))
+ .addTaskEdge(edge(taskNodeB3, taskNodeC3))
+ .addTaskEdge(edge(taskNodeB4, taskNodeC4))
+ .addTaskEdge(edge(taskNodeC3, taskNodeD2))
+ .addTaskEdge(edge(taskNodeC4, taskNodeD2))
+ .addTaskEdge(edge(taskNodeD2, null))
+ .build();
+
+ workflowDag(workflowDAG)
+ .nodeAssertion(node(nodeNameA1)
+ .exist()
+ .noInDegree()
+ .outDegrees(newArrayList(nodeNameB1, nodeNameB2)))
+ .nodeAssertion(node(nodeNameB1)
+ .exist()
+ .inDegrees(nodeNameA1)
+ .outDegrees(nodeNameC1))
+ .nodeAssertion(node(nodeNameB2)
+ .exist()
+ .inDegrees(nodeNameA1)
+ .outDegrees(nodeNameC2))
+ .nodeAssertion(node(nodeNameC1)
+ .exist()
+ .inDegrees(nodeNameB1)
+ .outDegrees(nodeNameD1))
+ .nodeAssertion(node(nodeNameC2)
+ .exist()
+ .inDegrees(nodeNameB2)
+ .outDegrees(nodeNameD1))
+ .nodeAssertion(node(nodeNameD1)
+ .exist()
+ .inDegrees(newArrayList(nodeNameC1, nodeNameC2))
+ .noOutDegree())
+ .doAssertion();
+ workflowDag(workflowDAG)
+ .nodeAssertion(node(nodeNameA2)
+ .exist()
+ .noInDegree()
+ .outDegrees(newArrayList(nodeNameB3, nodeNameB4)))
+ .nodeAssertion(node(nodeNameB3)
+ .exist()
+ .inDegrees(nodeNameA2)
+ .outDegrees(nodeNameC3))
+ .nodeAssertion(node(nodeNameB4)
+ .exist()
+ .inDegrees(nodeNameA2)
+ .outDegrees(nodeNameC4))
+ .nodeAssertion(node(nodeNameC3)
+ .exist()
+ .inDegrees(nodeNameB3)
+ .outDegrees(nodeNameD2))
+ .nodeAssertion(node(nodeNameC4)
+ .exist()
+ .inDegrees(nodeNameB4)
+ .outDegrees(nodeNameD2))
+ .nodeAssertion(node(nodeNameD2)
+ .exist()
+ .inDegrees(newArrayList(nodeNameC3, nodeNameC4))
+ .noOutDegree())
+ .doAssertion();
+ }
+
+ private DAGNodeDefinition dagNode(String nodeName) {
+ DAGNodeDefinition dagNodeDefinition = new DAGNodeDefinition();
+ dagNodeDefinition.setNodeName(nodeName);
+ return dagNodeDefinition;
+ }
+
+ private DAGEdge edge(DAGNodeDefinition from, DAGNodeDefinition to) {
+ DAGEdge dagEdge = new DAGEdge();
+ dagEdge.setFromNodeName(from == null ? null : from.getNodeName());
+ dagEdge.setToNodeName(to == null ? null : to.getNodeName());
+ return dagEdge;
+ }
+
+}
diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java b/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/engine/WorkflowEngineIT.java
similarity index 77%
rename from dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
rename to dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/engine/WorkflowEngineIT.java
index ac37c94438..0ba306f3cc 100644
--- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/exception/TaskExecutionContextCreateException.java
+++ b/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/engine/WorkflowEngineIT.java
@@ -15,12 +15,10 @@
* limitations under the License.
*/
-package org.apache.dolphinscheduler.server.master.exception;
+package org.apache.dolphinscheduler.workflow.engine.engine;
-public class TaskExecutionContextCreateException extends MasterException {
+public class WorkflowEngineIT {
- public TaskExecutionContextCreateException(String message) {
- super(message);
- }
+ private WorkflowEngine workflowEngine;
}
diff --git a/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/engine/WorkflowEngineTest.java b/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/engine/WorkflowEngineTest.java
new file mode 100644
index 0000000000..6e35706549
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/engine/WorkflowEngineTest.java
@@ -0,0 +1,105 @@
+package org.apache.dolphinscheduler.workflow.engine.engine;
+
+import static org.apache.dolphinscheduler.workflow.engine.assertions.WorkflowExecutionRunnableAssertions.workflowExecutionRunnable;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.apache.dolphinscheduler.workflow.engine.assertions.SingletonWorkflowExecuteRunnableRepositoryAssertions;
+import org.apache.dolphinscheduler.workflow.engine.event.WorkflowOperationEvent;
+import org.apache.dolphinscheduler.workflow.engine.exception.WorkflowExecuteRunnableNotFoundException;
+import org.apache.dolphinscheduler.workflow.engine.workflow.IWorkflowExecutionRunnable;
+import org.apache.dolphinscheduler.workflow.engine.workflow.MockWorkflowExecutionRunnableFactory;
+import org.apache.dolphinscheduler.workflow.engine.workflow.SingletonWorkflowExecuteRunnableRepository;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class WorkflowEngineTest {
+
+ private WorkflowEngine workflowEngine;
+
+ @BeforeEach
+ public void before() {
+ workflowEngine = new WorkflowEngine(SingletonWorkflowExecuteRunnableRepository.getInstance());
+ }
+
+ @AfterEach
+ public void after() {
+ SingletonWorkflowExecuteRunnableRepository.getInstance().clear();
+ }
+
+ @Test
+ void triggerWorkflow() {
+ IWorkflowExecutionRunnable mockWorkflowExecuteRunnable =
+ MockWorkflowExecutionRunnableFactory.createWorkflowExecutionRunnable();
+ Integer workflowInstanceId = mockWorkflowExecuteRunnable.getWorkflowExecutionContext().getWorkflowInstanceId();
+
+ workflowEngine.triggerWorkflow(mockWorkflowExecuteRunnable);
+ workflowExecutionRunnable(mockWorkflowExecuteRunnable)
+ .existEvent(WorkflowOperationEvent.triggerEvent(workflowInstanceId));
+ }
+
+ @Test
+ void pauseWorkflow_WorkflowNotExist() {
+ WorkflowExecuteRunnableNotFoundException exception =
+ assertThrows(WorkflowExecuteRunnableNotFoundException.class, () -> workflowEngine.pauseWorkflow(1));
+ assertEquals("WorkflowExecuteRunnable not found: [id=1]", exception.getMessage());
+ }
+
+ @Test
+ void pauseWorkflow_WorkflowExist() {
+ IWorkflowExecutionRunnable mockWorkflowExecuteRunnable =
+ MockWorkflowExecutionRunnableFactory.createWorkflowExecutionRunnable();
+ Integer workflowInstanceId =
+ mockWorkflowExecuteRunnable.getWorkflowExecutionContext().getWorkflowInstanceId();
+ SingletonWorkflowExecuteRunnableRepository.getInstance()
+ .storeWorkflowExecutionRunnable(mockWorkflowExecuteRunnable);
+
+ workflowEngine.pauseWorkflow(workflowInstanceId);
+ workflowExecutionRunnable(mockWorkflowExecuteRunnable)
+ .existEvent(WorkflowOperationEvent.pauseEvent(workflowInstanceId));
+ }
+
+ @Test
+ void killWorkflow_WorkflowNotExist() {
+ WorkflowExecuteRunnableNotFoundException exception =
+ assertThrows(WorkflowExecuteRunnableNotFoundException.class,
+ () -> workflowEngine.killWorkflow(1));
+ assertEquals("WorkflowExecuteRunnable not found: [id=1]", exception.getMessage());
+ }
+
+ @Test
+ void killWorkflow_WorkflowExist() {
+ IWorkflowExecutionRunnable mockWorkflowExecuteRunnable =
+ MockWorkflowExecutionRunnableFactory.createWorkflowExecutionRunnable();
+ Integer workflowInstanceId =
+ mockWorkflowExecuteRunnable.getWorkflowExecutionContext().getWorkflowInstanceId();
+ SingletonWorkflowExecuteRunnableRepository.getInstance()
+ .storeWorkflowExecutionRunnable(mockWorkflowExecuteRunnable);
+
+ workflowEngine.killWorkflow(workflowInstanceId);
+ workflowExecutionRunnable(mockWorkflowExecuteRunnable)
+ .existEvent(WorkflowOperationEvent.killEvent(workflowInstanceId));
+ }
+
+ @Test
+ void finalizeWorkflow_WorkflowNotExist() {
+ workflowEngine.finalizeWorkflow(-1);
+ }
+
+ @Test
+ void finalizeWorkflow_WorkflowExist() {
+ IWorkflowExecutionRunnable emptyWorkflowExecuteRunnable =
+ MockWorkflowExecutionRunnableFactory.createWorkflowExecutionRunnable();
+ Integer workflowInstanceId =
+ emptyWorkflowExecuteRunnable.getWorkflowExecutionContext().getWorkflowInstanceId();
+ SingletonWorkflowExecuteRunnableRepository.getInstance()
+ .storeWorkflowExecutionRunnable(emptyWorkflowExecuteRunnable);
+ SingletonWorkflowExecuteRunnableRepositoryAssertions.existWorkflowExecutionRunnable(workflowInstanceId);
+
+ workflowEngine.finalizeWorkflow(workflowInstanceId);
+ SingletonWorkflowExecuteRunnableRepositoryAssertions.notExistWorkflowExecutionRunnable(workflowInstanceId);
+ }
+
+}
diff --git a/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowOperationEventTest.java b/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowOperationEventTest.java
new file mode 100644
index 0000000000..8356fbb1ac
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/event/WorkflowOperationEventTest.java
@@ -0,0 +1,30 @@
+package org.apache.dolphinscheduler.workflow.engine.event;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+class WorkflowOperationEventTest {
+
+ @Test
+ void triggerEvent() {
+ WorkflowOperationEvent workflowOperationEvent = WorkflowOperationEvent.triggerEvent(1);
+ assertEquals(1, workflowOperationEvent.getWorkflowInstanceId());
+ assertEquals(WorkflowOperationType.TRIGGER, workflowOperationEvent.getWorkflowOperationType());
+ }
+
+ @Test
+ void pauseEvent() {
+ WorkflowOperationEvent workflowOperationEvent = WorkflowOperationEvent.pauseEvent(1);
+ assertEquals(1, workflowOperationEvent.getWorkflowInstanceId());
+ assertEquals(WorkflowOperationType.PAUSE, workflowOperationEvent.getWorkflowOperationType());
+ }
+
+ @Test
+ void killEvent() {
+ WorkflowOperationEvent workflowOperationEvent = WorkflowOperationEvent.killEvent(1);
+ assertEquals(1, workflowOperationEvent.getWorkflowInstanceId());
+ assertEquals(WorkflowOperationType.KILL, workflowOperationEvent.getWorkflowOperationType());
+ }
+
+}
diff --git a/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/workflow/MockWorkflowExecutionRunnableFactory.java b/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/workflow/MockWorkflowExecutionRunnableFactory.java
new file mode 100644
index 0000000000..94ecc00316
--- /dev/null
+++ b/dolphinscheduler-workflow-engine/src/test/java/org/apache/dolphinscheduler/workflow/engine/workflow/MockWorkflowExecutionRunnableFactory.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.workflow.engine.workflow;
+
+import org.apache.dolphinscheduler.workflow.engine.engine.DAGEngineFactory;
+import org.apache.dolphinscheduler.workflow.engine.event.MemoryEventRepository;
+
+import org.apache.commons.lang3.RandomUtils;
+
+public class MockWorkflowExecutionRunnableFactory {
+
+ private static final ITaskExecutionContextFactory taskExecutionContextFactory = new TaskExecutionContextFactory();
+ private static final ITaskExecutionRunnableFactory taskExecutionRunnableFactory =
+ new TaskExecutionRunnableFactory(taskExecutionContextFactory);
+ private static final DAGEngineFactory dagEngineFactory = new DAGEngineFactory(taskExecutionRunnableFactory);
+ private static final WorkflowExecutionRunnableFactory workflowExecutionRunnableFactory =
+ new WorkflowExecutionRunnableFactory(dagEngineFactory);
+
+ public static WorkflowExecutionRunnable createWorkflowExecutionRunnable() {
+ int workflowInstanceId = RandomUtils.nextInt();
+ String workflowInstanceName = "MockWorkflowInstance-" + workflowInstanceId;
+ WorkflowInstance workflowInstance = WorkflowInstance.of(workflowInstanceId, workflowInstanceName);
+ IWorkflowExecutionContext workflowExecutionContext = WorkflowExecutionContext.builder()
+ .workflowInstance(workflowInstance)
+ .eventRepository(MemoryEventRepository.newInstance())
+ .build();
+
+ return workflowExecutionRunnableFactory.createWorkflowExecutionRunnable(workflowExecutionContext);
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index 4a71741f8e..1390f531a1 100755
--- a/pom.xml
+++ b/pom.xml
@@ -57,6 +57,7 @@
<module>dolphinscheduler-storage-plugin</module>
<module>dolphinscheduler-extract</module>
<module>dolphinscheduler-dao-plugin</module>
+ <module>dolphinscheduler-workflow-engine</module>
</modules>
<properties>