From f56d51cc28ab4511e2688875da9870a46c57ee46 Mon Sep 17 00:00:00 2001 From: xiangzihao <460888207@qq.com> Date: Thu, 5 Dec 2024 15:09:27 +0800 Subject: [PATCH] [DSIP-72][Dynamic Task] Remove dynamic task type (#16842) * remove dynamic task type * remove dynamic task type * remove dynamic task type * resolve conflicts * resolve conflicts * resolve conflicts * fix comment * fix ci --- docs/configs/docsdev.js | 8 - docs/docs/en/guide/task/dynamic.md | 77 ---- docs/docs/en/guide/upgrade/incompatible.md | 1 + docs/docs/zh/guide/task/dynamic.md | 76 ---- docs/docs/zh/guide/upgrade/incompatible.md | 5 +- docs/img/tasks/demo/dynamic_definition.png | Bin 27885 -> 0 bytes docs/img/tasks/demo/dynamic_running.png | Bin 24718 -> 0 bytes docs/img/tasks/icons/dynamic.png | Bin 10606 -> 0 bytes .../dolphinscheduler/api/enums/Status.java | 2 - .../impl/WorkflowInstanceServiceImpl.java | 4 - .../src/main/resources/task-type-config.yaml | 1 - ...opWorkflowInstanceExecuteFunctionTest.java | 12 +- .../common/enums/WorkflowExecutionStatus.java | 21 +- .../utils/placeholder/BusinessTimeUtils.java | 1 - .../dao/entity/ListenerEvent.java | 88 ----- .../mysql/dolphinscheduler_dml.sql | 2 - .../postgresql/dolphinscheduler_dml.sql | 2 - .../impl/WorkflowInstanceDaoImplTest.java | 4 +- .../DynamicAsyncTaskExecuteFunction.java | 173 --------- .../plugin/dynamic/DynamicCommandUtils.java | 86 ----- .../plugin/dynamic/DynamicLogicTask.java | 339 ------------------ .../DynamicLogicTaskPluginFactory.java | 74 ---- .../plugin/dynamic/DynamicOutput.java | 33 -- .../statemachine/IWorkflowStateAction.java | 1 - .../WorkflowWaitToRunStateAction.java | 117 ------ .../subworkflow/SubWorkflowService.java | 2 - .../subworkflow/SubWorkflowServiceImpl.java | 8 - .../api/task/DynamicLogicTaskChannel.java | 30 -- .../task/DynamicLogicTaskChannelFactory.java | 38 -- .../plugin/task/api/utils/TaskTypeUtils.java | 5 - .../task/api/TaskPluginManagerTest.java | 2 - .../public/images/task-icons/dynamic.png | Bin 10606 -> 0 bytes .../images/task-icons/dynamic_hover.png | Bin 11229 -> 0 bytes .../src/locales/en_US/project.ts | 3 - .../src/locales/zh_CN/project.ts | 3 - .../src/store/project/task-type.ts | 3 - .../src/store/project/types.ts | 1 - .../task/components/node/detail-modal.tsx | 4 +- .../task/components/node/fields/index.ts | 1 - .../components/node/fields/use-dynamic.ts | 120 ------- .../task/components/node/format-data.ts | 10 +- .../task/components/node/tasks/index.ts | 2 - .../task/components/node/tasks/use-dynamic.ts | 83 ----- .../projects/task/constants/task-type.ts | 4 - .../workflow/components/dag/dag.module.scss | 6 - 45 files changed, 17 insertions(+), 1435 deletions(-) delete mode 100644 docs/docs/en/guide/task/dynamic.md delete mode 100644 docs/docs/zh/guide/task/dynamic.md delete mode 100644 docs/img/tasks/demo/dynamic_definition.png delete mode 100644 docs/img/tasks/demo/dynamic_running.png delete mode 100644 docs/img/tasks/icons/dynamic.png delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ListenerEvent.java delete mode 100644 dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicAsyncTaskExecuteFunction.java delete mode 100644 dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicCommandUtils.java delete mode 100644 dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicLogicTask.java delete mode 100644 dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicLogicTaskPluginFactory.java delete mode 100644 dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicOutput.java delete mode 100644 dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/workflow/statemachine/WorkflowWaitToRunStateAction.java delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/task/DynamicLogicTaskChannel.java delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/task/DynamicLogicTaskChannelFactory.java delete mode 100644 dolphinscheduler-ui/public/images/task-icons/dynamic.png delete mode 100644 dolphinscheduler-ui/public/images/task-icons/dynamic_hover.png delete mode 100644 dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-dynamic.ts delete mode 100644 dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dynamic.ts diff --git a/docs/configs/docsdev.js b/docs/configs/docsdev.js index 0fa7adf261..ef599cd118 100644 --- a/docs/configs/docsdev.js +++ b/docs/configs/docsdev.js @@ -101,10 +101,6 @@ export default { title: 'SubWorkflow', link: '/en-us/docs/dev/user_doc/guide/task/sub-workflow.html', }, - { - title: 'Dynamic', - link: '/en-us/docs/dev/user_doc/guide/task/dynamic.html', - }, { title: 'Dependent', link: '/en-us/docs/dev/user_doc/guide/task/dependent.html', @@ -816,10 +812,6 @@ export default { title: 'SubWorkflow', link: '/zh-cn/docs/dev/user_doc/guide/task/sub-workflow.html', }, - { - title: 'Dynamic', - link: '/zh-cn/docs/dev/user_doc/guide/task/dynamic.html', - }, { title: 'Dependent', link: '/zh-cn/docs/dev/user_doc/guide/task/dependent.html', diff --git a/docs/docs/en/guide/task/dynamic.md b/docs/docs/en/guide/task/dynamic.md deleted file mode 100644 index b304f78ee7..0000000000 --- a/docs/docs/en/guide/task/dynamic.md +++ /dev/null @@ -1,77 +0,0 @@ -# Dynamic Task - -## Overview - -Dynamic task can input multiple parameter lists, calculate all parameter combinations through Cartesian product, and then execute each parameter combination as a sub-workflow node. - -For example, we have a workflow with two input parameters, a, b. - -We can use the dynamic node to define this workflow definition as a node, and then enter the parameter list - -- Parameter a: a1, a2 -- Parameter b: b1, b2 - -Then the dynamic node will calculate four parameter combinations, which are -- a1, b1 -- a1, b2 -- a2, b1 -- a2, b2 - -Then execute these four parameter combinations as the startup parameters of the sub-workflow node, and a total of four sub-workflow nodes are generated. - -## Create Task - -- Click `Project -> Management-Project -> Name-Workflow Definition`, and click the "Create Workflow" button to enter the - DAG editing page. -- Drag from the toolbar task node to canvas. - -The task definition is shown in the following figure: - -![dynamic_definition](../../../../img/tasks/demo/dynamic_definition.png) - -## Task Parameters - -[//]: # (TODO: use the commented anchor below once our website template supports this syntax) -[//]: # (- Please refer to [DolphinScheduler Task Parameters Appendix](appendix.md#default-task-parameters) `Default Task Parameters` section for default parameters.) - -- Please refer to [DolphinScheduler Task Parameters Appendix](appendix.md) `Default Task Parameters` section for default parameters. - -| **Task Parameters** | **Description** | -|-----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Child Node | Select the workflow definition of the sub-workflow. You can jump to the workflow definition of the selected sub-workflow by entering the sub-node in the upper right corner. | -| max num of sub workflow instances | The maximum number of sub-workflow instances dynamically generated. After exceeding this upper limit, the dynamically generated sub-workflow instances will no longer be executed. | -| Parallelism | The parallelism of the sub-workflow instances dynamically generated, that is, the number of sub-workflow instances executed at the same time. | -| Param Value | The parameter of the sub-workflow instance dynamically generated, supports multiple parameters, and the parameters are separated by delimiters. | -| Filter Condition | The filter condition of the sub-workflow instance dynamically generated, supports multiple filter values, and the filter conditions are separated by commas, such as `2022,2023`, which will filter the parameter groups containing the values of 2022 and 2023. | - -## Task Parameters Output - -The output parameters of the dynamic node refer to the output parameters of the sub-workflow. The output parameters of all sub-workflows will be collected into a list as the output parameters of the dynamic node. - -When the downstream task is referenced, it can be referenced by `${dynamic.out(TaskName)}`. - -The value is a json, as shown below - -```Json -[ - { "dynParams":{ "a":"a1", "b":"b1" }, "outputValue":{ "p":"a1-b1" }, "mappedTimes":1 }, - { "dynParams":{ "a":"a2", "b":"b1" }, "outputValue":{ "p":"a2-b1" }, "mappedTimes":2 }, - { "dynParams":{ "a":"a3", "b":"b1" }, "outputValue":{ "p":"a3-b1" }, "mappedTimes":3 } -] -``` - -- `dynParams` the input parameters of the sub-workflow -- `outputValue` is the output parameter of the sub-workflow. For example, the `p` here is a string that splices the output parameters `a` and `b` of the sub-workflow and outputs them in the form of variables `p` -- `mappedTimes` is the index of the execution of the sub-workflow, starting from 1 - -## Running Status - -After the dynamic task is started, all parameter combinations will be calculated according to the input parameter list, and then a sub-workflow instance will be created for each parameter combination. - -When the dynamic task is running, it will periodically check the statistical information of all current sub-workflow instances. If the parallelism is greater than the number of sub-workflow instances running, it will trigger the start of the appropriate number of sub-workflow instances (the sub-workflow instances are created first, and then the start is triggered later). - -As shown below. - -![dynamic_running](../../../../img/tasks/demo/dynamic_running.png) - -The dynamic task will run successfully only when all sub-workflow instances are running successfully. diff --git a/docs/docs/en/guide/upgrade/incompatible.md b/docs/docs/en/guide/upgrade/incompatible.md index 12152c58a1..6ca21b2c0f 100644 --- a/docs/docs/en/guide/upgrade/incompatible.md +++ b/docs/docs/en/guide/upgrade/incompatible.md @@ -36,4 +36,5 @@ This document records the incompatible updates between each version. You need to * Remove the `registry-disconnect-strategy` in `application.yaml` ([#16821])(https://github.com/apache/dolphinscheduler/pull/16821) * Remove `exec-threads` in worker's `application.yaml`, please use `physical-task-config`;Remove `master-async-task-executor-thread-pool-size` in master's `application.yaml`, please use `logic-task-config` ([#16790])(https://github.com/apache/dolphinscheduler/pull/16790) * Drop unused column `other_params_json` in `t_ds_worker_group` ([#16860])(https://github.com/apache/dolphinscheduler/pull/16860) +* Remove the `Dynamic` from the `Task Plugin` ([#16482])(https://github.com/apache/dolphinscheduler/pull/16842) diff --git a/docs/docs/zh/guide/task/dynamic.md b/docs/docs/zh/guide/task/dynamic.md deleted file mode 100644 index ee1d20adb1..0000000000 --- a/docs/docs/zh/guide/task/dynamic.md +++ /dev/null @@ -1,76 +0,0 @@ -# 动态节点 - -## 综述 - -动态节点可以通过输入多个参数列表,通过笛卡尔积计算出多所有的参数组合,然后将每个参数组合作为一个子工作流节点执行。 - -比如我们有一个工作流,它具有两个输入参数,a, b。 -我们可以通过动态节点,将这个工作流定义当做一个节点,然后输入参数列表 -- 参数a:a1, a2 -- 参数b:b1, b2 - -那么动态节点会计算出四个参数组合,分别是 -- a1, b1 -- a1, b2 -- a2, b1 -- a2, b2 - -然后将这四个参数组合作为子工作流节点的启动参数执行,共生成四个子工作流节点。 - -## 创建任务 - -- 点击项目管理 -> 项目名称 -> 工作流定义,点击”创建工作流”按钮,进入 DAG 编辑页面: - -- 拖动工具栏的 任务节点到画板中。 - -任务定义如下图所示: - -![dynamic_definition](../../../../img/tasks/demo/dynamic_definition.png) - -## 任务参数 - -[//]: # (TODO: use the commented anchor below once our website template supports this syntax) -[//]: # (- 默认参数说明请参考[DolphinScheduler任务参数附录](appendix.md#默认任务参数)`默认任务参数`一栏。) - -- 默认参数说明请参考[DolphinScheduler任务参数附录](appendix.md)`默认任务参数`一栏。 - -| **任务参数** | **描述** | -|----------|------------------------------------------------------------------------------| -| 子节点 | 是选择子工作流的工作流定义,右上角进入该子节点可以跳转到所选子工作流的工作流定义 | -| 动态生成实例上限 | 是指动态生成的子工作流实例的上限,超过该上限后,动态生成的子工作流实例将不再执行 | -| 并行度 | 是指动态生成的子工作流实例的并行度,即同时执行的子工作流实例的数量 | -| 取值参数 | 是指动态生成的子工作流实例的参数,支持多个参数,参数之间用分隔符分隔 | -| 过滤条件 | 是指动态生成的子工作流实例的过滤条件,支持多个过滤值,过滤条件之间用逗号分隔, 如 `2022,2023`, 则会过来包含2022和2023的值的参数组 | - -## 任务参数输出 - -动态节点的输出参数,是指子工作流的输出参数,所有子工作流的输出参数都会被收集到一个列表中,作为动态节点的输出参数。 - -下游任务引用的时候,可以通过 `${dynamic.out(TaskName)}` 的方式引用。 - -值为一个json,样例如下 - -```Json -[ - { "dynParams":{ "a":"a1", "b":"b1" }, "outputValue":{ "p":"a1-b1" }, "mappedTimes":1 }, - { "dynParams":{ "a":"a2", "b":"b1" }, "outputValue":{ "p":"a2-b1" }, "mappedTimes":2 }, - { "dynParams":{ "a":"a3", "b":"b1" }, "outputValue":{ "p":"a3-b1" }, "mappedTimes":3 } -] -``` - -其中 -- `dynParams` 是子工作流的输入参数 -- `outputValue` 是子工作流的输出参数, 如这里的`p`为将子工作流的输出参数`a`和`b`拼接起来的字符串,以变量`p`的形式输出 -- `mappedTimes` 是子工作流的执行的index,从1开始 - -## 运行状态 - -Dynamic任务启动后,会根据输入参数列表,计算出所有的参数组合,然后对每一个参数组合,创建一个子工作流实例。 - -Dynamic运行时,会定期检测当前所有子工作流实例的统计信息,如果并行度大于运行中的子工作流实例的数量,则会触发启动合适数量的工作流实例(工作流实例是先创建,后续再出发启动)。 - -如下如所示。 - -![dynamic_running](../../../../img/tasks/demo/dynamic_running.png) - -当且进度所有的子工作流实例全部运行成功时,dynamic任务才会运行成功。 diff --git a/docs/docs/zh/guide/upgrade/incompatible.md b/docs/docs/zh/guide/upgrade/incompatible.md index 530e006c9c..927d8df78a 100644 --- a/docs/docs/zh/guide/upgrade/incompatible.md +++ b/docs/docs/zh/guide/upgrade/incompatible.md @@ -32,6 +32,7 @@ * 废弃从 1.x 至 2.x 的升级代码 ([#16543])(https://github.com/apache/dolphinscheduler/pull/16543) * 移除 `数据质量` 模块 ([#16794])(https://github.com/apache/dolphinscheduler/pull/16794) * 在`application.yaml`中移除`registry-disconnect-strategy`配置 ([#16821])(https://github.com/apache/dolphinscheduler/pull/16821) -* 在worker的`application.yaml`中移除`exec-threads`,使用`physical-task-config`替代;在master的`application.yaml`中移除`master-async-task-executor-thread-pool-size`使用`logic-task-config`替代 ([#16790])(https://github.com/apache/dolphinscheduler/pull/16790) -* 在`t_ds_worker_group` 表中移除 无用的`other_params_json`字段 ([#16860])(https://github.com/apache/dolphinscheduler/pull/16860) +* 在 `worker` 的 `application.yaml` 中移除 `exec-threads`,使用`physical-task-config`替代;在master的`application.yaml`中移除`master-async-task-executor-thread-pool-size`使用`logic-task-config`替代 ([#16790])(https://github.com/apache/dolphinscheduler/pull/16790) +* 在 `t_ds_worker_group` 表中移除 无用的 `other_params_json` 字段 ([#16860])(https://github.com/apache/dolphinscheduler/pull/16860) +* 从 `任务插件` 中移除 `Dynamic` 类型 ([#16482])(https://github.com/apache/dolphinscheduler/pull/16842) diff --git a/docs/img/tasks/demo/dynamic_definition.png b/docs/img/tasks/demo/dynamic_definition.png deleted file mode 100644 index e3eef9fa2c0fee679eae3e0470e2989989af93d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27885 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 diff --git a/docs/img/tasks/icons/dynamic.png b/docs/img/tasks/icons/dynamic.png deleted file mode 100644 index 6df7485872789a1b93883843c7bb94abf418a608..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10606 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 relationSubWorkflows = relationSubWorkflowMapper .queryAllSubWorkflowInstance((long) taskInstance.getWorkflowInstanceId(), taskInstance.getTaskCode()); diff --git a/dolphinscheduler-api/src/main/resources/task-type-config.yaml b/dolphinscheduler-api/src/main/resources/task-type-config.yaml index 56053b74bd..81e964903f 100644 --- a/dolphinscheduler-api/src/main/resources/task-type-config.yaml +++ b/dolphinscheduler-api/src/main/resources/task-type-config.yaml @@ -41,7 +41,6 @@ task: - 'DEPENDENT' - 'CONDITIONS' - 'SWITCH' - - 'DYNAMIC' dataIntegration: - 'SEATUNNEL' - 'DATAX' diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/executor/workflow/StopWorkflowInstanceExecuteFunctionTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/executor/workflow/StopWorkflowInstanceExecuteFunctionTest.java index 74ba73e2f0..9c6fa6ac5e 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/executor/workflow/StopWorkflowInstanceExecuteFunctionTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/executor/workflow/StopWorkflowInstanceExecuteFunctionTest.java @@ -50,8 +50,7 @@ class StopWorkflowInstanceExecuteFunctionTest { "RUNNING_EXECUTION", "READY_PAUSE", "READY_STOP", - "SERIAL_WAIT", - "WAIT_TO_RUN"}) + "SERIAL_WAIT"}) void exceptionIfWorkflowInstanceCannotStop_canStop(WorkflowExecutionStatus workflowExecutionStatus) { WorkflowInstance workflowInstance = new WorkflowInstance(); workflowInstance.setName("Workflow-1"); @@ -65,8 +64,7 @@ class StopWorkflowInstanceExecuteFunctionTest { "RUNNING_EXECUTION", "READY_PAUSE", "READY_STOP", - "SERIAL_WAIT", - "WAIT_TO_RUN"}, mode = EnumSource.Mode.EXCLUDE) + "SERIAL_WAIT"}, mode = EnumSource.Mode.EXCLUDE) void exceptionIfWorkflowInstanceCannotStop_canNotStop(WorkflowExecutionStatus workflowExecutionStatus) { WorkflowInstance workflowInstance = new WorkflowInstance(); workflowInstance.setName("Workflow-1"); @@ -81,8 +79,7 @@ class StopWorkflowInstanceExecuteFunctionTest { @ParameterizedTest @EnumSource(value = WorkflowExecutionStatus.class, names = { - "SERIAL_WAIT", - "WAIT_TO_RUN"}) + "SERIAL_WAIT"}) void ifWorkflowInstanceCanDirectStopInDB_canDirectStopInDB(WorkflowExecutionStatus workflowExecutionStatus) { WorkflowInstance workflowInstance = new WorkflowInstance(); workflowInstance.setName("Workflow-1"); @@ -93,8 +90,7 @@ class StopWorkflowInstanceExecuteFunctionTest { @ParameterizedTest @EnumSource(value = WorkflowExecutionStatus.class, names = { - "SERIAL_WAIT", - "WAIT_TO_RUN"}, mode = EnumSource.Mode.EXCLUDE) + "SERIAL_WAIT"}, mode = EnumSource.Mode.EXCLUDE) void ifWorkflowInstanceCanDirectStopInDB_canNotDirectStopInDB(WorkflowExecutionStatus workflowExecutionStatus) { WorkflowInstance workflowInstance = new WorkflowInstance(); workflowInstance.setName("Workflow-1"); diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/WorkflowExecutionStatus.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/WorkflowExecutionStatus.java index caacc22deb..00e4c87e2a 100644 --- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/WorkflowExecutionStatus.java +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/WorkflowExecutionStatus.java @@ -20,10 +20,12 @@ package org.apache.dolphinscheduler.common.enums; import java.util.HashMap; import java.util.Map; +import lombok.Getter; import lombok.NonNull; import com.baomidou.mybatisplus.annotation.EnumValue; +@Getter public enum WorkflowExecutionStatus { SUBMITTED_SUCCESS(0, "submitted"), @@ -35,7 +37,6 @@ public enum WorkflowExecutionStatus { FAILURE(6, "failure"), SUCCESS(7, "success"), SERIAL_WAIT(14, "serial wait"), - WAIT_TO_RUN(17, "wait to run"), FAILOVER(18, "failover"); private static final Map CODE_MAP = new HashMap<>(); @@ -50,8 +51,7 @@ public enum WorkflowExecutionStatus { RUNNING_EXECUTION.getCode(), READY_PAUSE.getCode(), READY_STOP.getCode(), - SERIAL_WAIT.getCode(), - WAIT_TO_RUN.getCode() + SERIAL_WAIT.getCode() }; static { @@ -80,12 +80,11 @@ public enum WorkflowExecutionStatus { return this == RUNNING_EXECUTION || this == READY_PAUSE || this == READY_STOP - || this == SERIAL_WAIT - || this == WAIT_TO_RUN; + || this == SERIAL_WAIT; } public boolean canDirectStopInDB() { - return this == SERIAL_WAIT || this == WAIT_TO_RUN; + return this == SERIAL_WAIT; } public boolean canPause() { @@ -95,7 +94,7 @@ public enum WorkflowExecutionStatus { } public boolean canDirectPauseInDB() { - return this == SERIAL_WAIT || this == WAIT_TO_RUN; + return this == SERIAL_WAIT; } public boolean isFinished() { @@ -145,14 +144,6 @@ public enum WorkflowExecutionStatus { this.desc = desc; } - public int getCode() { - return code; - } - - public String getDesc() { - return desc; - } - @Override public String toString() { return name(); diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/placeholder/BusinessTimeUtils.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/placeholder/BusinessTimeUtils.java index 6d6e5497d4..9d30aa71ca 100644 --- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/placeholder/BusinessTimeUtils.java +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/placeholder/BusinessTimeUtils.java @@ -59,7 +59,6 @@ public class BusinessTimeUtils { case RECOVER_SUSPENDED_PROCESS: case START_FAILURE_TASK_PROCESS: case REPEAT_RUNNING: - case DYNAMIC_GENERATION: case SCHEDULER: default: businessDate = addDays(new Date(), -1); diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ListenerEvent.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ListenerEvent.java deleted file mode 100644 index 36fe939ce8..0000000000 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ListenerEvent.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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.dao.entity; - -import org.apache.dolphinscheduler.common.enums.AlertStatus; -import org.apache.dolphinscheduler.common.enums.ListenerEventType; - -import java.util.Date; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; - -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -@TableName("t_ds_listener_event") -public class ListenerEvent { - - /** - * primary key - */ - @TableId(value = "id", type = IdType.AUTO) - private Integer id; - - /** - * content - */ - @TableField(value = "content") - private String content; - - /** - * sign - */ - @TableField(value = "sign") - private String sign; - - /** - * alert_status - */ - @TableField(value = "event_type") - private ListenerEventType eventType; - - /** - * post_status - */ - @TableField("post_status") - private AlertStatus postStatus; - - /** - * log - */ - @TableField("log") - private String log; - /** - * create_time - */ - @TableField("create_time") - private Date createTime; - - /** - * update_time - */ - @TableField("update_time") - private Date updateTime; -} diff --git a/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/mysql/dolphinscheduler_dml.sql b/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/mysql/dolphinscheduler_dml.sql index 780325d42f..2f6a4566d8 100644 --- a/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/mysql/dolphinscheduler_dml.sql +++ b/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/mysql/dolphinscheduler_dml.sql @@ -19,5 +19,3 @@ UPDATE t_ds_task_definition SET task_type = 'SUB_WORKFLOW' WHERE task_type = 'SU UPDATE t_ds_task_definition_log SET task_type = 'SUB_WORKFLOW' WHERE task_type = 'SUB_PROCESS'; UPDATE t_ds_task_definition SET task_params = replace(task_params, 'processDefinitionCode', 'workflowDefinitionCode') where task_type = 'SUB_WORKFLOW'; UPDATE t_ds_task_definition_log SET task_params = replace(task_params, 'processDefinitionCode', 'workflowDefinitionCode') where task_type = 'SUB_WORKFLOW'; -UPDATE t_ds_task_definition SET task_params = replace(task_params, 'processDefinitionCode', 'workflowDefinitionCode') where task_type = 'DYNAMIC'; -UPDATE t_ds_task_definition_log SET task_params = replace(task_params, 'processDefinitionCode', 'workflowDefinitionCode') where task_type = 'DYNAMIC'; diff --git a/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/postgresql/dolphinscheduler_dml.sql b/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/postgresql/dolphinscheduler_dml.sql index 780325d42f..2f6a4566d8 100644 --- a/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/postgresql/dolphinscheduler_dml.sql +++ b/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/postgresql/dolphinscheduler_dml.sql @@ -19,5 +19,3 @@ UPDATE t_ds_task_definition SET task_type = 'SUB_WORKFLOW' WHERE task_type = 'SU UPDATE t_ds_task_definition_log SET task_type = 'SUB_WORKFLOW' WHERE task_type = 'SUB_PROCESS'; UPDATE t_ds_task_definition SET task_params = replace(task_params, 'processDefinitionCode', 'workflowDefinitionCode') where task_type = 'SUB_WORKFLOW'; UPDATE t_ds_task_definition_log SET task_params = replace(task_params, 'processDefinitionCode', 'workflowDefinitionCode') where task_type = 'SUB_WORKFLOW'; -UPDATE t_ds_task_definition SET task_params = replace(task_params, 'processDefinitionCode', 'workflowDefinitionCode') where task_type = 'DYNAMIC'; -UPDATE t_ds_task_definition_log SET task_params = replace(task_params, 'processDefinitionCode', 'workflowDefinitionCode') where task_type = 'DYNAMIC'; diff --git a/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/repository/impl/WorkflowInstanceDaoImplTest.java b/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/repository/impl/WorkflowInstanceDaoImplTest.java index a12c57abea..520a9b907e 100644 --- a/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/repository/impl/WorkflowInstanceDaoImplTest.java +++ b/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/repository/impl/WorkflowInstanceDaoImplTest.java @@ -64,9 +64,7 @@ class WorkflowInstanceDaoImplTest extends BaseDaoTest { WorkflowExecutionStatus.READY_STOP)); workflowInstanceDao.insert(createWorkflowInstance(workflowDefinitionCode, workflowDefinitionVersion, WorkflowExecutionStatus.SERIAL_WAIT)); - workflowInstanceDao.insert(createWorkflowInstance(workflowDefinitionCode, workflowDefinitionVersion, - WorkflowExecutionStatus.WAIT_TO_RUN)); - assertEquals(5, workflowInstanceDao + assertEquals(4, workflowInstanceDao .queryByWorkflowCodeVersionStatus(workflowDefinitionCode, workflowDefinitionVersion, status).size()); } diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicAsyncTaskExecuteFunction.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicAsyncTaskExecuteFunction.java deleted file mode 100644 index b8ba05fe7a..0000000000 --- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicAsyncTaskExecuteFunction.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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.engine.executor.plugin.dynamic; - -import static org.apache.dolphinscheduler.common.constants.CommandKeyConstants.CMD_DYNAMIC_START_PARAMS; - -import org.apache.dolphinscheduler.common.utils.JSONUtils; -import org.apache.dolphinscheduler.dao.entity.Command; -import org.apache.dolphinscheduler.dao.entity.TaskInstance; -import org.apache.dolphinscheduler.dao.entity.WorkflowInstance; -import org.apache.dolphinscheduler.dao.mapper.CommandMapper; -import org.apache.dolphinscheduler.plugin.task.api.TaskExecutionContext; -import org.apache.dolphinscheduler.plugin.task.api.enums.DataType; -import org.apache.dolphinscheduler.plugin.task.api.enums.Direct; -import org.apache.dolphinscheduler.plugin.task.api.enums.TaskExecutionStatus; -import org.apache.dolphinscheduler.plugin.task.api.model.Property; -import org.apache.dolphinscheduler.service.subworkflow.SubWorkflowService; - -import java.time.Duration; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import lombok.NonNull; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public class DynamicAsyncTaskExecuteFunction { - - private static final Duration TASK_EXECUTE_STATE_CHECK_INTERVAL = Duration.ofSeconds(10); - - private static final String OUTPUT_KEY = "dynamic.out"; - - private final WorkflowInstance workflowInstance; - - private final TaskInstance taskInstance; - - private final SubWorkflowService subWorkflowService; - - private final CommandMapper commandMapper; - - private final int degreeOfParallelism; - - private final DynamicLogicTask logicTask; - - public DynamicAsyncTaskExecuteFunction(TaskExecutionContext taskExecutionContext, - WorkflowInstance workflowInstance, - TaskInstance taskInstance, - DynamicLogicTask dynamicLogicTask, - CommandMapper commandMapper, - SubWorkflowService subWorkflowService, - int degreeOfParallelism) { - this.workflowInstance = workflowInstance; - this.taskInstance = taskInstance; - this.logicTask = dynamicLogicTask; - this.degreeOfParallelism = degreeOfParallelism; - - this.commandMapper = commandMapper; - this.subWorkflowService = subWorkflowService; - } - - public @NonNull TaskExecutionStatus getAsyncTaskExecutionStatus() { - List allSubWorkflowInstance = getAllSubProcessInstance(); - int totalSubProcessInstanceCount = allSubWorkflowInstance.size(); - - List finishedSubWorkflowInstance = - subWorkflowService.filterFinishProcessInstances(allSubWorkflowInstance); - - if (finishedSubWorkflowInstance.size() == totalSubProcessInstanceCount) { - log.info("all sub process instance finish"); - int successCount = subWorkflowService.filterSuccessProcessInstances(finishedSubWorkflowInstance).size(); - log.info("success sub process instance count: {}", successCount); - if (successCount == totalSubProcessInstanceCount) { - log.info("all sub process instance success"); - setOutputParameters(); - return TaskExecutionStatus.SUCCESS; - } else { - int failedCount = totalSubProcessInstanceCount - successCount; - log.info("failed sub process instance count: {}", failedCount); - return TaskExecutionStatus.FAILURE; - } - } - - if (logicTask.isCancel()) { - return TaskExecutionStatus.FAILURE; - } - - int runningCount = subWorkflowService.filterRunningProcessInstances(allSubWorkflowInstance).size(); - int startCount = degreeOfParallelism - runningCount; - if (startCount > 0) { - log.info("There are {} sub process instances that can be started", startCount); - startSubProcessInstances(allSubWorkflowInstance, startCount); - } - // query the status of sub workflow instance - return TaskExecutionStatus.RUNNING_EXECUTION; - } - - private void setOutputParameters() { - log.info("set varPool"); - List allSubWorkflowInstance = getAllSubProcessInstance(); - - List dynamicOutputs = new ArrayList<>(); - int index = 1; - for (WorkflowInstance workflowInstance : allSubWorkflowInstance) { - DynamicOutput dynamicOutput = new DynamicOutput(); - Map dynamicParams = - JSONUtils.toMap(JSONUtils.toMap(workflowInstance.getCommandParam()).get(CMD_DYNAMIC_START_PARAMS)); - dynamicOutput.setDynParams(dynamicParams); - - Map outputValueMap = new HashMap<>(); - List propertyList = subWorkflowService.getWorkflowOutputParameters(workflowInstance); - for (Property property : propertyList) { - outputValueMap.put(property.getProp(), property.getValue()); - } - - dynamicOutput.setOutputValue(outputValueMap); - dynamicOutput.setMappedTimes(index++); - dynamicOutputs.add(dynamicOutput); - } - - Property property = new Property(); - property.setProp(String.format("%s(%s)", OUTPUT_KEY, taskInstance.getName())); - property.setDirect(Direct.OUT); - property.setType(DataType.VARCHAR); - property.setValue(JSONUtils.toJsonString(dynamicOutputs)); - - List taskPropertyList = new ArrayList<>(JSONUtils.toList(taskInstance.getVarPool(), Property.class)); - taskPropertyList.add(property); - // logicTask.getTaskParameters().setVarPool(JSONUtils.toJsonString(taskPropertyList)); - - log.info("set property: {}", property); - } - - private void startSubProcessInstances(List allSubWorkflowInstance, int startCount) { - List waitingWorkflowInstances = - subWorkflowService.filterWaitToRunProcessInstances(allSubWorkflowInstance); - - for (int i = 0; i < Math.min(startCount, waitingWorkflowInstances.size()); i++) { - WorkflowInstance subWorkflowInstance = waitingWorkflowInstances.get(i); - Map parameters = JSONUtils.toMap(DynamicCommandUtils - .getDataFromCommandParam(subWorkflowInstance.getCommandParam(), CMD_DYNAMIC_START_PARAMS)); - Command command = DynamicCommandUtils.createCommand(this.workflowInstance, - subWorkflowInstance.getWorkflowDefinitionCode(), subWorkflowInstance.getWorkflowDefinitionVersion(), - parameters); - command.setWorkflowInstanceId(subWorkflowInstance.getId()); - commandMapper.insert(command); - log.info("start sub process instance, sub process instance id: {}, command: {}", - subWorkflowInstance.getId(), - command); - } - } - - public List getAllSubProcessInstance() { - return subWorkflowService.getAllDynamicSubWorkflow(workflowInstance.getId(), taskInstance.getTaskCode()); - } - -} diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicCommandUtils.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicCommandUtils.java deleted file mode 100644 index 2dc76c9e72..0000000000 --- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicCommandUtils.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.engine.executor.plugin.dynamic; - -import org.apache.dolphinscheduler.common.constants.CommandKeyConstants; -import org.apache.dolphinscheduler.common.enums.CommandType; -import org.apache.dolphinscheduler.common.enums.TaskDependType; -import org.apache.dolphinscheduler.common.utils.JSONUtils; -import org.apache.dolphinscheduler.dao.entity.Command; -import org.apache.dolphinscheduler.dao.entity.WorkflowInstance; -import org.apache.dolphinscheduler.plugin.task.api.model.Property; - -import org.apache.commons.lang3.StringUtils; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.google.common.collect.Lists; - -public class DynamicCommandUtils { - - static public Command createCommand(WorkflowInstance workflowInstance, - Long subProcessDefinitionCode, - Integer subProcessDefinitionVersion, - Map parameters) { - Command command = new Command(); - if (workflowInstance.getCommandType().equals(CommandType.START_PROCESS)) { - command.setCommandType(CommandType.DYNAMIC_GENERATION); - } else { - command.setCommandType(workflowInstance.getCommandType()); - } - command.setWorkflowDefinitionCode(subProcessDefinitionCode); - command.setWorkflowDefinitionVersion(subProcessDefinitionVersion); - command.setTaskDependType(TaskDependType.TASK_POST); - command.setFailureStrategy(workflowInstance.getFailureStrategy()); - command.setWarningType(workflowInstance.getWarningType()); - - String globalParams = workflowInstance.getGlobalParams(); - if (StringUtils.isNotEmpty(globalParams)) { - List parentParams = Lists.newArrayList(JSONUtils.toList(globalParams, Property.class)); - for (Property parentParam : parentParams) { - parameters.put(parentParam.getProp(), parentParam.getValue()); - } - } - - addDataToCommandParam(command, CommandKeyConstants.CMD_PARAM_START_PARAMS, JSONUtils.toJsonString(parameters)); - command.setExecutorId(workflowInstance.getExecutorId()); - command.setWarningGroupId(workflowInstance.getWarningGroupId()); - command.setWorkflowInstancePriority(workflowInstance.getWorkflowInstancePriority()); - command.setWorkerGroup(workflowInstance.getWorkerGroup()); - command.setDryRun(workflowInstance.getDryRun()); - command.setTenantCode(workflowInstance.getTenantCode()); - return command; - } - - static public String getDataFromCommandParam(String commandParam, String key) { - Map cmdParam = JSONUtils.toMap(commandParam); - return cmdParam.get(key); - } - - static void addDataToCommandParam(Command command, String key, String data) { - Map cmdParam = JSONUtils.toMap(command.getCommandParam()); - if (cmdParam == null) { - cmdParam = new HashMap<>(); - } - cmdParam.put(key, data); - command.setCommandParam(JSONUtils.toJsonString(cmdParam)); - } - -} diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicLogicTask.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicLogicTask.java deleted file mode 100644 index 40fd7ab69b..0000000000 --- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicLogicTask.java +++ /dev/null @@ -1,339 +0,0 @@ -/* - * 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.engine.executor.plugin.dynamic; - -import org.apache.dolphinscheduler.common.constants.CommandKeyConstants; -import org.apache.dolphinscheduler.common.enums.Flag; -import org.apache.dolphinscheduler.common.enums.WorkflowExecutionStatus; -import org.apache.dolphinscheduler.common.utils.JSONUtils; -import org.apache.dolphinscheduler.dao.entity.Command; -import org.apache.dolphinscheduler.dao.entity.RelationSubWorkflow; -import org.apache.dolphinscheduler.dao.entity.TaskInstance; -import org.apache.dolphinscheduler.dao.entity.WorkflowDefinition; -import org.apache.dolphinscheduler.dao.entity.WorkflowInstance; -import org.apache.dolphinscheduler.dao.mapper.CommandMapper; -import org.apache.dolphinscheduler.dao.mapper.WorkflowDefinitionMapper; -import org.apache.dolphinscheduler.dao.repository.TaskInstanceDao; -import org.apache.dolphinscheduler.dao.repository.WorkflowInstanceDao; -import org.apache.dolphinscheduler.extract.base.client.Clients; -import org.apache.dolphinscheduler.extract.master.IWorkflowControlClient; -import org.apache.dolphinscheduler.extract.master.transportor.workflow.WorkflowInstanceStopRequest; -import org.apache.dolphinscheduler.extract.master.transportor.workflow.WorkflowInstanceStopResponse; -import org.apache.dolphinscheduler.plugin.task.api.TaskExecutionContext; -import org.apache.dolphinscheduler.plugin.task.api.enums.TaskExecutionStatus; -import org.apache.dolphinscheduler.plugin.task.api.model.DynamicInputParameter; -import org.apache.dolphinscheduler.plugin.task.api.model.Property; -import org.apache.dolphinscheduler.plugin.task.api.parameters.DynamicParameters; -import org.apache.dolphinscheduler.plugin.task.api.utils.ParameterUtils; -import org.apache.dolphinscheduler.server.master.engine.executor.plugin.AbstractLogicTask; -import org.apache.dolphinscheduler.server.master.engine.executor.plugin.ITaskParameterDeserializer; -import org.apache.dolphinscheduler.server.master.exception.MasterTaskExecuteException; -import org.apache.dolphinscheduler.service.process.ProcessService; -import org.apache.dolphinscheduler.service.subworkflow.SubWorkflowService; - -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import lombok.extern.slf4j.Slf4j; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.google.common.collect.Lists; - -@Slf4j -public class DynamicLogicTask extends AbstractLogicTask { - - public static final String TASK_TYPE = "DYNAMIC"; - private final WorkflowInstanceDao workflowInstanceDao; - - private final SubWorkflowService subWorkflowService; - - private final WorkflowDefinitionMapper workflowDefinitionMapper; - - private final CommandMapper commandMapper; - - private final ProcessService processService; - - private WorkflowInstance workflowInstance; - - private TaskInstance taskInstance; - - private final TaskExecutionContext taskExecutionContext; - - private boolean haveBeenCanceled = false; - - public DynamicLogicTask(TaskExecutionContext taskExecutionContext, - WorkflowInstanceDao workflowInstanceDao, - TaskInstanceDao taskInstanceDao, - SubWorkflowService subWorkflowService, - ProcessService processService, - WorkflowDefinitionMapper workflowDefinitionMapper, - CommandMapper commandMapper) { - super(taskExecutionContext); - this.taskExecutionContext = taskExecutionContext; - this.workflowInstanceDao = workflowInstanceDao; - this.subWorkflowService = subWorkflowService; - this.processService = processService; - this.workflowDefinitionMapper = workflowDefinitionMapper; - this.commandMapper = commandMapper; - - this.workflowInstance = workflowInstanceDao.queryById(taskExecutionContext.getWorkflowInstanceId()); - this.taskInstance = taskInstanceDao.queryById(taskExecutionContext.getTaskInstanceId()); - } - - // public AsyncTaskExecuteFunction getAsyncTaskExecuteFunction() throws MasterTaskExecuteException { - // List> parameterGroup = generateParameterGroup(); - // - // if (parameterGroup.size() > dynamicParameters.getMaxNumOfSubWorkflowInstances()) { - // log.warn("the number of sub process instances [{}] exceeds the maximum limit [{}]", parameterGroup.size(), - // dynamicParameters.getMaxNumOfSubWorkflowInstances()); - // parameterGroup = parameterGroup.subList(0, dynamicParameters.getMaxNumOfSubWorkflowInstances()); - // } - // - // // if already exists sub process instance, do not generate again - // List existsSubWorkflowInstanceList = - // subWorkflowService.getAllDynamicSubWorkflow(workflowInstance.getId(), taskInstance.getTaskCode()); - // if (CollectionUtils.isEmpty(existsSubWorkflowInstanceList)) { - // generateSubWorkflowInstance(parameterGroup); - // } else { - // resetProcessInstanceStatus(existsSubWorkflowInstanceList); - // } - // return new DynamicAsyncTaskExecuteFunction(taskExecutionContext, workflowInstance, taskInstance, this, - // commandMapper, - // subWorkflowService, dynamicParameters.getDegreeOfParallelism()); - // } - - public void resetProcessInstanceStatus(List existsSubWorkflowInstanceList) { - switch (workflowInstance.getCommandType()) { - case REPEAT_RUNNING: - existsSubWorkflowInstanceList.forEach(processInstance -> { - processInstance.setState(WorkflowExecutionStatus.WAIT_TO_RUN); - workflowInstanceDao.updateById(processInstance); - }); - break; - case START_FAILURE_TASK_PROCESS: - case RECOVER_TOLERANCE_FAULT_PROCESS: - List failedWorkflowInstances = - subWorkflowService.filterFailedProcessInstances(existsSubWorkflowInstanceList); - failedWorkflowInstances.forEach(processInstance -> { - processInstance.setState(WorkflowExecutionStatus.WAIT_TO_RUN); - workflowInstanceDao.updateById(processInstance); - }); - break; - } - } - - public void generateSubWorkflowInstance(List> parameterGroup) throws MasterTaskExecuteException { - List workflowInstanceList = new ArrayList<>(); - WorkflowDefinition subWorkflowDefinition = - workflowDefinitionMapper.queryByCode(taskParameters.getWorkflowDefinitionCode()); - for (Map parameters : parameterGroup) { - String dynamicStartParams = JSONUtils.toJsonString(parameters); - Command command = DynamicCommandUtils.createCommand(workflowInstance, subWorkflowDefinition.getCode(), - subWorkflowDefinition.getVersion(), parameters); - // todo: set id to -1? we use command to generate sub process instance, but the generate method will use the - // command id to do - // somethings - command.setId(-1); - DynamicCommandUtils.addDataToCommandParam(command, CommandKeyConstants.CMD_DYNAMIC_START_PARAMS, - dynamicStartParams); - WorkflowInstance subWorkflowInstance = createSubProcessInstance(command); - subWorkflowInstance.setState(WorkflowExecutionStatus.WAIT_TO_RUN); - workflowInstanceDao.insert(subWorkflowInstance); - command.setWorkflowInstanceId(subWorkflowInstance.getId()); - workflowInstanceList.add(subWorkflowInstance); - } - - List relationSubWorkflowList = new ArrayList<>(); - for (WorkflowInstance subWorkflowInstance : workflowInstanceList) { - RelationSubWorkflow relationSubWorkflow = new RelationSubWorkflow(); - relationSubWorkflow.setParentWorkflowInstanceId(Long.valueOf(workflowInstance.getId())); - relationSubWorkflow.setParentTaskCode(taskInstance.getTaskCode()); - relationSubWorkflow.setSubWorkflowInstanceId(Long.valueOf(subWorkflowInstance.getId())); - relationSubWorkflowList.add(relationSubWorkflow); - } - - log.info("Expected number of runs : {}, actual number of runs : {}", parameterGroup.size(), - workflowInstanceList.size()); - - int insertN = subWorkflowService.batchInsertRelationSubWorkflow(relationSubWorkflowList); - log.info("insert {} relation sub workflow", insertN); - } - - public WorkflowInstance createSubProcessInstance(Command command) throws MasterTaskExecuteException { - WorkflowInstance subWorkflowInstance; - try { - subWorkflowInstance = processService.constructWorkflowInstance(command, workflowInstance.getHost()); - subWorkflowInstance.setIsSubWorkflow(Flag.YES); - subWorkflowInstance.setVarPool(taskExecutionContext.getVarPool()); - } catch (Exception e) { - log.error("create sub process instance error", e); - throw new MasterTaskExecuteException(e.getMessage()); - } - return subWorkflowInstance; - } - - public List> generateParameterGroup() { - List dynamicInputParameters = getDynamicInputParameters(); - Set filterStrings = - Arrays.stream(StringUtils.split(taskParameters.getFilterCondition(), ",")).map(String::trim) - .collect(Collectors.toSet()); - - List> allParameters = new ArrayList<>(); - for (DynamicInputParameter dynamicInputParameter : dynamicInputParameters) { - List singleParameters = new ArrayList<>(); - String value = dynamicInputParameter.getValue(); - String separator = dynamicInputParameter.getSeparator(); - List valueList = - Arrays.stream(StringUtils.split(value, separator)).map(String::trim).collect(Collectors.toList()); - - valueList = valueList.stream().filter(v -> !filterStrings.contains(v)).collect(Collectors.toList()); - - for (String v : valueList) { - DynamicInputParameter singleParameter = new DynamicInputParameter(); - singleParameter.setName(dynamicInputParameter.getName()); - singleParameter.setValue(v); - singleParameters.add(singleParameter); - } - allParameters.add(singleParameters); - } - - // use Sets.cartesianProduct to get the cartesian product of all parameters - List> cartesianProduct = Lists.cartesianProduct(allParameters); - - // convert cartesian product to parameter group List> - List> parameterGroup = cartesianProduct.stream().map( - inputParameterList -> inputParameterList.stream().collect( - Collectors.toMap(DynamicInputParameter::getName, DynamicInputParameter::getValue))) - .collect(Collectors.toList()); - - log.info("parameter group size: {}", parameterGroup.size()); - // log every parameter group - if (CollectionUtils.isNotEmpty(parameterGroup)) { - for (Map map : parameterGroup) { - log.info("parameter group: {}", map); - } - } - return parameterGroup; - } - - private List getDynamicInputParameters() { - List dynamicInputParameters = taskParameters.getListParameters(); - if (CollectionUtils.isNotEmpty(dynamicInputParameters)) { - for (DynamicInputParameter dynamicInputParameter : dynamicInputParameters) { - String value = dynamicInputParameter.getValue(); - Map paramsMap = taskExecutionContext.getPrepareParamsMap(); - value = ParameterUtils.convertParameterPlaceholders(value, ParameterUtils.convert(paramsMap)); - dynamicInputParameter.setValue(value); - } - } - return dynamicInputParameters; - } - - @Override - public void start() throws MasterTaskExecuteException { - // todo: - } - - @Override - public TaskExecutionStatus getTaskExecutionState() { - return taskExecutionContext.getCurrentExecutionStatus(); - } - - @Override - public void pause() throws MasterTaskExecuteException { - // todo: support pause - } - - @Override - public void kill() { - try { - doKillSubWorkflowInstances(); - } catch (MasterTaskExecuteException e) { - log.error("kill {} error", taskInstance.getName(), e); - } - } - - @Override - public ITaskParameterDeserializer getTaskParameterDeserializer() { - return taskParamsJson -> JSONUtils.parseObject(taskParamsJson, new TypeReference() { - }); - } - - private void doKillSubWorkflowInstances() throws MasterTaskExecuteException { - List existsSubWorkflowInstanceList = - subWorkflowService.getAllDynamicSubWorkflow(workflowInstance.getId(), taskInstance.getTaskCode()); - if (CollectionUtils.isEmpty(existsSubWorkflowInstanceList)) { - return; - } - - commandMapper.deleteByWorkflowInstanceIds( - existsSubWorkflowInstanceList.stream().map(WorkflowInstance::getId).collect(Collectors.toList())); - - List runningSubWorkflowInstanceList = - subWorkflowService.filterRunningProcessInstances(existsSubWorkflowInstanceList); - doKillRunningSubWorkflowInstances(runningSubWorkflowInstanceList); - - List waitToRunWorkflowInstances = - subWorkflowService.filterWaitToRunProcessInstances(existsSubWorkflowInstanceList); - doKillWaitToRunSubWorkflowInstances(waitToRunWorkflowInstances); - - this.haveBeenCanceled = true; - } - - private void doKillRunningSubWorkflowInstances(List runningSubWorkflowInstanceList) throws MasterTaskExecuteException { - for (WorkflowInstance subWorkflowInstance : runningSubWorkflowInstanceList) { - try { - WorkflowInstanceStopResponse workflowInstanceStopResponse = Clients - .withService(IWorkflowControlClient.class) - .withHost(subWorkflowInstance.getHost()) - .stopWorkflowInstance(new WorkflowInstanceStopRequest(subWorkflowInstance.getId())); - if (workflowInstanceStopResponse.isSuccess()) { - log.info("Stop SubWorkflow: {} successfully", subWorkflowInstance.getName()); - } else { - throw new MasterTaskExecuteException( - "Stop subWorkflow: " + subWorkflowInstance.getName() + " failed"); - } - } catch (MasterTaskExecuteException me) { - throw me; - } catch (Exception e) { - throw new MasterTaskExecuteException( - String.format("Send stop request to SubWorkflow's master: %s failed", - subWorkflowInstance.getHost()), - e); - } - } - } - - private void doKillWaitToRunSubWorkflowInstances(List waitToRunWorkflowInstances) { - for (WorkflowInstance subWorkflowInstance : waitToRunWorkflowInstances) { - subWorkflowInstance.setState(WorkflowExecutionStatus.STOP); - workflowInstanceDao.updateById(subWorkflowInstance); - } - } - - public boolean isCancel() { - return haveBeenCanceled; - } -} diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicLogicTaskPluginFactory.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicLogicTaskPluginFactory.java deleted file mode 100644 index 5065e80c7f..0000000000 --- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicLogicTaskPluginFactory.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.engine.executor.plugin.dynamic; - -import org.apache.dolphinscheduler.dao.mapper.CommandMapper; -import org.apache.dolphinscheduler.dao.mapper.WorkflowDefinitionMapper; -import org.apache.dolphinscheduler.dao.repository.TaskInstanceDao; -import org.apache.dolphinscheduler.dao.repository.WorkflowInstanceDao; -import org.apache.dolphinscheduler.plugin.task.api.TaskExecutionContext; -import org.apache.dolphinscheduler.server.master.engine.executor.plugin.ILogicTaskPluginFactory; -import org.apache.dolphinscheduler.service.process.ProcessService; -import org.apache.dolphinscheduler.service.subworkflow.SubWorkflowService; -import org.apache.dolphinscheduler.task.executor.ITaskExecutor; - -import lombok.extern.slf4j.Slf4j; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@Slf4j -@Component -public class DynamicLogicTaskPluginFactory implements ILogicTaskPluginFactory { - - @Autowired - private WorkflowInstanceDao workflowInstanceDao; - - @Autowired - private TaskInstanceDao taskInstanceDao; - - @Autowired - private WorkflowDefinitionMapper processDefineMapper; - - @Autowired - private CommandMapper commandMapper; - - @Autowired - private ProcessService processService; - - @Autowired - SubWorkflowService subWorkflowService; - - @Override - public DynamicLogicTask createLogicTask(final ITaskExecutor taskExecutor) { - final TaskExecutionContext taskExecutionContext = taskExecutor.getTaskExecutionContext(); - return new DynamicLogicTask(taskExecutionContext, - workflowInstanceDao, - taskInstanceDao, - subWorkflowService, - processService, - processDefineMapper, - commandMapper); - - } - - @Override - public String getTaskType() { - return DynamicLogicTask.TASK_TYPE; - } -} diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicOutput.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicOutput.java deleted file mode 100644 index c727fcb08e..0000000000 --- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/executor/plugin/dynamic/DynamicOutput.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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.engine.executor.plugin.dynamic; - -import java.util.Map; - -import lombok.Data; - -@Data -public class DynamicOutput { - - private Map dynParams; - - private Map outputValue; - - private int mappedTimes; - -} diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/workflow/statemachine/IWorkflowStateAction.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/workflow/statemachine/IWorkflowStateAction.java index b2f12702d5..5bac4ada66 100644 --- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/workflow/statemachine/IWorkflowStateAction.java +++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/workflow/statemachine/IWorkflowStateAction.java @@ -43,7 +43,6 @@ import org.apache.dolphinscheduler.server.master.engine.workflow.runnable.IWorkf * @see WorkflowFailedStateAction * @see WorkflowSuccessStateAction * @see WorkflowFailoverStateAction - * @see WorkflowWaitToRunStateAction */ public interface IWorkflowStateAction { diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/workflow/statemachine/WorkflowWaitToRunStateAction.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/workflow/statemachine/WorkflowWaitToRunStateAction.java deleted file mode 100644 index b9af3c2d8c..0000000000 --- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/workflow/statemachine/WorkflowWaitToRunStateAction.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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.engine.workflow.statemachine; - -import org.apache.dolphinscheduler.common.enums.WorkflowExecutionStatus; -import org.apache.dolphinscheduler.server.master.engine.workflow.lifecycle.event.WorkflowFailedLifecycleEvent; -import org.apache.dolphinscheduler.server.master.engine.workflow.lifecycle.event.WorkflowFinalizeLifecycleEvent; -import org.apache.dolphinscheduler.server.master.engine.workflow.lifecycle.event.WorkflowPauseLifecycleEvent; -import org.apache.dolphinscheduler.server.master.engine.workflow.lifecycle.event.WorkflowPausedLifecycleEvent; -import org.apache.dolphinscheduler.server.master.engine.workflow.lifecycle.event.WorkflowStartLifecycleEvent; -import org.apache.dolphinscheduler.server.master.engine.workflow.lifecycle.event.WorkflowStopLifecycleEvent; -import org.apache.dolphinscheduler.server.master.engine.workflow.lifecycle.event.WorkflowStoppedLifecycleEvent; -import org.apache.dolphinscheduler.server.master.engine.workflow.lifecycle.event.WorkflowSucceedLifecycleEvent; -import org.apache.dolphinscheduler.server.master.engine.workflow.lifecycle.event.WorkflowTopologyLogicalTransitionWithTaskFinishLifecycleEvent; -import org.apache.dolphinscheduler.server.master.engine.workflow.runnable.IWorkflowExecutionRunnable; - -import lombok.extern.slf4j.Slf4j; - -import org.springframework.stereotype.Component; - -@Slf4j -@Component -public class WorkflowWaitToRunStateAction extends AbstractWorkflowStateAction { - - @Override - public void startEventAction(final IWorkflowExecutionRunnable workflowExecutionRunnable, - final WorkflowStartLifecycleEvent workflowStartEvent) { - throwExceptionIfStateIsNotMatch(workflowExecutionRunnable); - logWarningIfCannotDoAction(workflowExecutionRunnable, workflowStartEvent); - } - - @Override - public void topologyLogicalTransitionEventAction( - final IWorkflowExecutionRunnable workflowExecutionRunnable, - final WorkflowTopologyLogicalTransitionWithTaskFinishLifecycleEvent workflowTopologyLogicalTransitionWithTaskFinishEvent) { - throwExceptionIfStateIsNotMatch(workflowExecutionRunnable); - logWarningIfCannotDoAction(workflowExecutionRunnable, workflowTopologyLogicalTransitionWithTaskFinishEvent); - } - - @Override - public void pauseEventAction(final IWorkflowExecutionRunnable workflowExecutionRunnable, - final WorkflowPauseLifecycleEvent workflowPauseEvent) { - throwExceptionIfStateIsNotMatch(workflowExecutionRunnable); - logWarningIfCannotDoAction(workflowExecutionRunnable, workflowPauseEvent); - } - - @Override - public void pausedEventAction(final IWorkflowExecutionRunnable workflowExecutionRunnable, - final WorkflowPausedLifecycleEvent workflowPausedEvent) { - throwExceptionIfStateIsNotMatch(workflowExecutionRunnable); - logWarningIfCannotDoAction(workflowExecutionRunnable, workflowPausedEvent); - } - - @Override - public void stopEventAction(final IWorkflowExecutionRunnable workflowExecutionRunnable, - final WorkflowStopLifecycleEvent workflowStopEvent) { - throwExceptionIfStateIsNotMatch(workflowExecutionRunnable); - logWarningIfCannotDoAction(workflowExecutionRunnable, workflowStopEvent); - } - - @Override - public void stoppedEventAction(final IWorkflowExecutionRunnable workflowExecutionRunnable, - final WorkflowStoppedLifecycleEvent workflowStoppedEvent) { - throwExceptionIfStateIsNotMatch(workflowExecutionRunnable); - logWarningIfCannotDoAction(workflowExecutionRunnable, workflowStoppedEvent); - } - - @Override - public void succeedEventAction(final IWorkflowExecutionRunnable workflowExecutionRunnable, - final WorkflowSucceedLifecycleEvent workflowSucceedEvent) { - throwExceptionIfStateIsNotMatch(workflowExecutionRunnable); - logWarningIfCannotDoAction(workflowExecutionRunnable, workflowSucceedEvent); - } - - @Override - public void failedEventAction(final IWorkflowExecutionRunnable workflowExecutionRunnable, - final WorkflowFailedLifecycleEvent workflowFailedEvent) { - throwExceptionIfStateIsNotMatch(workflowExecutionRunnable); - logWarningIfCannotDoAction(workflowExecutionRunnable, workflowFailedEvent); - } - - @Override - public void finalizeEventAction(final IWorkflowExecutionRunnable workflowExecutionRunnable, - final WorkflowFinalizeLifecycleEvent workflowFinalizeEvent) { - throwExceptionIfStateIsNotMatch(workflowExecutionRunnable); - logWarningIfCannotDoAction(workflowExecutionRunnable, workflowFinalizeEvent); - } - - @Override - public WorkflowExecutionStatus matchState() { - return WorkflowExecutionStatus.WAIT_TO_RUN; - } - - /** - * The running state can only finish with success/failure. - */ - @Override - protected void emitWorkflowFinishedEventIfApplicable(final IWorkflowExecutionRunnable workflowExecutionRunnable) { - log.warn("The workflow: {} is in wait_to_run state, shouldn't emit workflow finished event", - workflowExecutionRunnable.getName()); - } -} diff --git a/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/subworkflow/SubWorkflowService.java b/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/subworkflow/SubWorkflowService.java index b845de41dd..ae50ddaa2a 100644 --- a/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/subworkflow/SubWorkflowService.java +++ b/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/subworkflow/SubWorkflowService.java @@ -38,8 +38,6 @@ public interface SubWorkflowService { List filterRunningProcessInstances(List workflowInstanceList); - List filterWaitToRunProcessInstances(List workflowInstanceList); - List filterFailedProcessInstances(List workflowInstanceList); List getWorkflowOutputParameters(WorkflowInstance workflowInstance); diff --git a/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/subworkflow/SubWorkflowServiceImpl.java b/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/subworkflow/SubWorkflowServiceImpl.java index 22d9396d07..cbdc996722 100644 --- a/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/subworkflow/SubWorkflowServiceImpl.java +++ b/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/subworkflow/SubWorkflowServiceImpl.java @@ -17,7 +17,6 @@ package org.apache.dolphinscheduler.service.subworkflow; -import org.apache.dolphinscheduler.common.enums.WorkflowExecutionStatus; import org.apache.dolphinscheduler.common.utils.JSONUtils; import org.apache.dolphinscheduler.dao.entity.RelationSubWorkflow; import org.apache.dolphinscheduler.dao.entity.WorkflowDefinitionLog; @@ -84,13 +83,6 @@ public class SubWorkflowServiceImpl implements SubWorkflowService { .filter(subProcessInstance -> subProcessInstance.getState().isRunning()).collect(Collectors.toList()); } - @Override - public List filterWaitToRunProcessInstances(List workflowInstanceList) { - return workflowInstanceList.stream() - .filter(subProcessInstance -> subProcessInstance.getState().equals(WorkflowExecutionStatus.WAIT_TO_RUN)) - .collect(Collectors.toList()); - } - @Override public List filterFailedProcessInstances(List workflowInstanceList) { return workflowInstanceList.stream() diff --git a/dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/task/DynamicLogicTaskChannel.java b/dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/task/DynamicLogicTaskChannel.java deleted file mode 100644 index d9f066d773..0000000000 --- a/dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/task/DynamicLogicTaskChannel.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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.plugin.task.api.task; - -import org.apache.dolphinscheduler.common.utils.JSONUtils; -import org.apache.dolphinscheduler.plugin.task.api.parameters.AbstractParameters; -import org.apache.dolphinscheduler.plugin.task.api.parameters.DynamicParameters; - -public class DynamicLogicTaskChannel extends AbstractLogicTaskChannel { - - @Override - public AbstractParameters parseParameters(String taskParams) { - return JSONUtils.parseObject(taskParams, DynamicParameters.class); - } -} diff --git a/dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/task/DynamicLogicTaskChannelFactory.java b/dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/task/DynamicLogicTaskChannelFactory.java deleted file mode 100644 index 0164e3ba53..0000000000 --- a/dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/task/DynamicLogicTaskChannelFactory.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.plugin.task.api.task; - -import org.apache.dolphinscheduler.plugin.task.api.TaskChannel; -import org.apache.dolphinscheduler.plugin.task.api.TaskChannelFactory; - -import com.google.auto.service.AutoService; - -@AutoService(TaskChannelFactory.class) -public class DynamicLogicTaskChannelFactory implements TaskChannelFactory { - - public static final String NAME = "DYNAMIC"; - @Override - public String getName() { - return NAME; - } - - @Override - public TaskChannel create() { - return new DynamicLogicTaskChannel(); - } -} diff --git a/dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/utils/TaskTypeUtils.java b/dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/utils/TaskTypeUtils.java index 26a632c52b..40059d1b1c 100644 --- a/dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/utils/TaskTypeUtils.java +++ b/dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/utils/TaskTypeUtils.java @@ -23,7 +23,6 @@ import org.apache.dolphinscheduler.plugin.task.api.ILogicTaskChannel; import org.apache.dolphinscheduler.plugin.task.api.TaskPluginManager; import org.apache.dolphinscheduler.plugin.task.api.task.ConditionsLogicTaskChannelFactory; import org.apache.dolphinscheduler.plugin.task.api.task.DependentLogicTaskChannelFactory; -import org.apache.dolphinscheduler.plugin.task.api.task.DynamicLogicTaskChannelFactory; import org.apache.dolphinscheduler.plugin.task.api.task.SubWorkflowLogicTaskChannelFactory; import org.apache.dolphinscheduler.plugin.task.api.task.SwitchLogicTaskChannelFactory; @@ -50,10 +49,6 @@ public class TaskTypeUtils { return DependentLogicTaskChannelFactory.NAME.equals(taskType); } - public boolean isDynamicTask(String taskType) { - return DynamicLogicTaskChannelFactory.NAME.equals(taskType); - } - public boolean isLogicTask(String taskType) { checkArgument(StringUtils.isNotEmpty(taskType), "taskType cannot be empty"); return TaskPluginManager.getTaskChannel(taskType) instanceof ILogicTaskChannel; diff --git a/dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/test/java/org/apache/dolphinscheduler/plugin/task/api/TaskPluginManagerTest.java b/dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/test/java/org/apache/dolphinscheduler/plugin/task/api/TaskPluginManagerTest.java index a380af488f..cde0579d2e 100644 --- a/dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/test/java/org/apache/dolphinscheduler/plugin/task/api/TaskPluginManagerTest.java +++ b/dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/test/java/org/apache/dolphinscheduler/plugin/task/api/TaskPluginManagerTest.java @@ -21,7 +21,6 @@ import static com.google.common.truth.Truth.assertThat; import org.apache.dolphinscheduler.plugin.task.api.task.ConditionsLogicTaskChannelFactory; import org.apache.dolphinscheduler.plugin.task.api.task.DependentLogicTaskChannelFactory; -import org.apache.dolphinscheduler.plugin.task.api.task.DynamicLogicTaskChannelFactory; import org.apache.dolphinscheduler.plugin.task.api.task.SubWorkflowLogicTaskChannelFactory; import org.apache.dolphinscheduler.plugin.task.api.task.SwitchLogicTaskChannelFactory; @@ -34,7 +33,6 @@ class TaskPluginManagerTest { @ValueSource(strings = { ConditionsLogicTaskChannelFactory.NAME, DependentLogicTaskChannelFactory.NAME, - DynamicLogicTaskChannelFactory.NAME, SubWorkflowLogicTaskChannelFactory.NAME, SwitchLogicTaskChannelFactory.NAME}) void testGetTaskChannel_logicTaskChannel(String type) { diff --git a/dolphinscheduler-ui/public/images/task-icons/dynamic.png b/dolphinscheduler-ui/public/images/task-icons/dynamic.png deleted file mode 100644 index 6df7485872789a1b93883843c7bb94abf418a608..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10606 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 diff --git a/dolphinscheduler-ui/src/locales/en_US/project.ts b/dolphinscheduler-ui/src/locales/en_US/project.ts index 910b364c01..7e0f0a1314 100644 --- a/dolphinscheduler-ui/src/locales/en_US/project.ts +++ b/dolphinscheduler-ui/src/locales/en_US/project.ts @@ -894,9 +894,6 @@ export default { filter_condition: 'Filter Condition', params_value: 'Params Value', separator: 'Separator', - dynamic_name_tips: 'name(required)', - dynamic_value_tips: 'params or value(required)', - dynamic_separator_tips: 'separator(required)', child_node_definition: 'child node definition', child_node_instance: 'child node instance', yarn_queue: 'Yarn Queue', diff --git a/dolphinscheduler-ui/src/locales/zh_CN/project.ts b/dolphinscheduler-ui/src/locales/zh_CN/project.ts index 58d48b796b..28d0fa6017 100644 --- a/dolphinscheduler-ui/src/locales/zh_CN/project.ts +++ b/dolphinscheduler-ui/src/locales/zh_CN/project.ts @@ -864,9 +864,6 @@ export default { filter_condition: '过滤条件', params_value: '取值参数', separator: '分隔符', - dynamic_name_tips: 'name(必填)', - dynamic_value_tips: 'params or value(必填)', - dynamic_separator_tips: '分隔符(必填)', child_node_definition: '子节点定义', child_node_instance: '子节点实例', yarn_queue: 'Yarn队列', diff --git a/dolphinscheduler-ui/src/store/project/task-type.ts b/dolphinscheduler-ui/src/store/project/task-type.ts index b655a08149..fee1ab16b6 100644 --- a/dolphinscheduler-ui/src/store/project/task-type.ts +++ b/dolphinscheduler-ui/src/store/project/task-type.ts @@ -32,9 +32,6 @@ export const TASK_TYPES_MAP = { SUB_WORKFLOW: { alias: 'SUB_WORKFLOW' }, - DYNAMIC: { - alias: 'DYNAMIC' - }, PROCEDURE: { alias: 'PROCEDURE' }, diff --git a/dolphinscheduler-ui/src/store/project/types.ts b/dolphinscheduler-ui/src/store/project/types.ts index bf2d4df3ce..1c56300ed2 100644 --- a/dolphinscheduler-ui/src/store/project/types.ts +++ b/dolphinscheduler-ui/src/store/project/types.ts @@ -23,7 +23,6 @@ type TaskExecuteType = 'STREAM' | 'BATCH' type TaskType = | 'SHELL' | 'SUB_WORKFLOW' - | 'DYNAMIC' | 'PROCEDURE' | 'SQL' | 'SPARK' diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/detail-modal.tsx b/dolphinscheduler-ui/src/views/projects/task/components/node/detail-modal.tsx index 66bc7559ae..d8cb54df94 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/detail-modal.tsx +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/detail-modal.tsx @@ -179,9 +179,7 @@ const NodeDetailModal = defineComponent({ }, { text: t('project.node.enter_this_child_node'), - show: - props.data.taskType === 'SUB_WORKFLOW' || - props.data.taskType === 'DYNAMIC', + show: props.data.taskType === 'SUB_WORKFLOW', disabled: !props.data.id || (router.currentRoute.value.name === 'workflow-instance-detail' && diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/fields/index.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/fields/index.ts index cbbe8a7032..45f2c79aa0 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/fields/index.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/fields/index.ts @@ -88,6 +88,5 @@ export { useKubeflow } from './use-kubeflow' export { useLinkis } from './use-linkis' export { useDataFactory } from './use-data-factory' export { useRemoteShell } from './use-remote-shell' -export { useDynamic } from './use-dynamic' export { useYarnQueue } from './use-queue' export { useAliyunServerlessSpark } from './use-aliyun-serverless-spark' diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-dynamic.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-dynamic.ts deleted file mode 100644 index 08e47c2d98..0000000000 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-dynamic.ts +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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. - */ - -import type { IJsonItem } from '../types' -import { useI18n } from 'vue-i18n' - -export function useDynamic(model: { [field: string]: any }): IJsonItem[] { - const { t } = useI18n() - - return [ - { - type: 'input-number', - field: 'maxNumOfSubWorkflowInstances', - span: 12, - name: t('project.node.max_num_of_sub_workflow_instances'), - validate: { - required: true - } - }, - { - type: 'input-number', - field: 'degreeOfParallelism', - span: 12, - name: t('project.node.parallelism'), - validate: { - required: true - } - }, - { - type: 'custom-parameters', - field: 'listParameters', - name: t('project.node.params_value'), - span: 24, - children: [ - { - type: 'input', - field: 'name', - span: 8, - props: { - placeholder: t('project.node.dynamic_name_tips'), - maxLength: 256 - }, - validate: { - trigger: ['input', 'blur'], - required: true, - validator(validate: any, value: string) { - if (!value) { - return new Error(t('project.node.dynamic_name_tips')) - } - - const sameItems = model['listParameters'].filter( - (item: { name: string }) => item.name === value - ) - - if (sameItems.length > 1) { - return new Error(t('project.node.prop_repeat')) - } - } - } - }, - { - type: 'input', - field: 'value', - span: 8, - props: { - placeholder: t('project.node.dynamic_value_tips'), - maxLength: 256 - }, - validate: { - trigger: ['input', 'blur'], - required: true, - validator(validate: any, value: string) { - if (!value) { - return new Error(t('project.node.dynamic_value_tips')) - } - } - } - }, - { - type: 'input', - field: 'separator', - span: 4, - props: { - placeholder: t('project.node.dynamic_separator_tips'), - maxLength: 256 - }, - validate: { - trigger: ['input', 'blur'], - required: true, - validator(validate: any, value: string) { - if (!value) { - return new Error(t('project.node.dynamic_separator_tips')) - } - } - } - } - ] - }, - { - type: 'input', - field: 'filterCondition', - span: 24, - name: t('project.node.filter_condition') - } - ] -} diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/format-data.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/format-data.ts index 57c658dd9a..9e7449c439 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/format-data.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/format-data.ts @@ -34,7 +34,7 @@ export function formatParams(data: INodeData): { } { const rdbmsSourceTypes = ref(['MYSQL', 'ORACLE', 'SQLSERVER', 'HANA']) const taskParams: ITaskParams = {} - if (data.taskType === 'SUB_WORKFLOW' || data.taskType === 'DYNAMIC') { + if (data.taskType === 'SUB_WORKFLOW') { taskParams.workflowDefinitionCode = data.workflowDefinitionCode } @@ -454,14 +454,6 @@ export function formatParams(data: INodeData): { taskParams.datasource = data.datasource } - if (data.taskType === 'DYNAMIC') { - taskParams.workflowDefinitionCode = data.workflowDefinitionCode - taskParams.maxNumOfSubWorkflowInstances = data.maxNumOfSubWorkflowInstances - taskParams.degreeOfParallelism = data.degreeOfParallelism - taskParams.filterCondition = data.filterCondition - taskParams.listParameters = data.listParameters - } - let timeoutNotifyStrategy = '' if (data.timeoutNotifyStrategy) { if (data.timeoutNotifyStrategy.length === 1) { diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/index.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/index.ts index e98d709a44..321b22d83e 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/index.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/index.ts @@ -50,13 +50,11 @@ import { useKubeflow } from './use-kubeflow' import { useLinkis } from './use-linkis' import { useDataFactory } from './use-data-factory' import { useRemoteShell } from './use-remote-shell' -import { useDynamic } from './use-dynamic' import { useAliyunServerlessSpark } from './use-aliyun-serverless-spark' export default { SHELL: useShell, SUB_WORKFLOW: useSubWorkflow, - DYNAMIC: useDynamic, PYTHON: usePython, SPARK: useSpark, MR: useMr, diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dynamic.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dynamic.ts deleted file mode 100644 index 8d20d87c9f..0000000000 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-dynamic.ts +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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. - */ - -import { reactive } from 'vue' -import { useRouter } from 'vue-router' -import * as Fields from '../fields/index' -import type { IJsonItem, INodeData } from '../types' -import { ITaskData } from '../types' - -export function useDynamic({ - projectCode, - from = 0, - readonly, - data -}: { - projectCode: number - from?: number - readonly?: boolean - data?: ITaskData -}) { - const router = useRouter() - const workflowCode = router.currentRoute.value.params.code - const model = reactive({ - taskType: 'DYNAMIC', - name: '', - flag: 'YES', - description: '', - timeoutFlag: false, - localParams: [], - environmentCode: null, - failRetryInterval: 1, - failRetryTimes: 0, - workerGroup: 'default', - delayTime: 0, - timeout: 30, - maxNumOfSubWorkflowInstances: 1024, - degreeOfParallelism: 1, - filterCondition: '', - listParameters: [{ name: null, value: null, separator: ',' }] - } as INodeData) - - if (model.listParameters?.length) { - model.listParameters[0].disabled = true - } - - return { - json: [ - Fields.useName(from), - ...Fields.useTaskDefinition({ projectCode, from, readonly, data, model }), - Fields.useRunFlag(), - Fields.useDescription(), - Fields.useTaskPriority(), - Fields.useWorkerGroup(projectCode), - Fields.useEnvironmentName(model, !data?.id), - ...Fields.useTaskGroup(model, projectCode), - ...Fields.useTimeoutAlarm(model), - Fields.useChildNode({ - model, - projectCode, - from, - workflowName: data?.workflowDefinitionName, - code: from === 1 ? 0 : Number(workflowCode) - }), - ...Fields.useDynamic(model), - Fields.usePreTasks() - ] as IJsonItem[], - model - } -} diff --git a/dolphinscheduler-ui/src/views/projects/task/constants/task-type.ts b/dolphinscheduler-ui/src/views/projects/task/constants/task-type.ts index aeea696dd8..8dc08a02d3 100644 --- a/dolphinscheduler-ui/src/views/projects/task/constants/task-type.ts +++ b/dolphinscheduler-ui/src/views/projects/task/constants/task-type.ts @@ -17,7 +17,6 @@ export type TaskType = | 'SHELL' | 'SUB_WORKFLOW' - | 'DYNAMIC' | 'PROCEDURE' | 'SQL' | 'SPARK' @@ -65,9 +64,6 @@ export const TASK_TYPES_MAP = { SUB_WORKFLOW: { alias: 'SUB_WORKFLOW' }, - DYNAMIC: { - alias: 'DYNAMIC' - }, PROCEDURE: { alias: 'PROCEDURE' }, diff --git a/dolphinscheduler-ui/src/views/projects/workflow/components/dag/dag.module.scss b/dolphinscheduler-ui/src/views/projects/workflow/components/dag/dag.module.scss index 217059b0ed..7dc3ac0249 100644 --- a/dolphinscheduler-ui/src/views/projects/workflow/components/dag/dag.module.scss +++ b/dolphinscheduler-ui/src/views/projects/workflow/components/dag/dag.module.scss @@ -107,9 +107,6 @@ $bgLight: #ffffff; &.icon-sub_workflow { background-image: url('/images/task-icons/sub_workflow.png'); } - &.icon-dynamic { - background-image: url('/images/task-icons/dynamic.png'); - } &.icon-procedure { background-image: url('/images/task-icons/procedure.png'); } @@ -220,9 +217,6 @@ $bgLight: #ffffff; &.icon-sub_workflow { background-image: url('/images/task-icons/sub_workflow_hover.png'); } - &.icon-dynamic { - background-image: url('/images/task-icons/dynamic_hover.png'); - } &.icon-procedure { background-image: url('/images/task-icons/procedure_hover.png'); }