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>