|
| 1 | +# 工作流分支节点设计文档 |
| 2 | + |
| 3 | +## 1. 文档信息 |
| 4 | +- 版本:1.20.0 |
| 5 | +- 状态:已更新 |
| 6 | +- 实现方案:节点属性 `branch.rules` 驱动 |
| 7 | + |
| 8 | +## 2. 设计结论 |
| 9 | +当前实现采用: |
| 10 | +- 分支节点类型:`workflow.branch` |
| 11 | +- 规则配置位置:分支节点属性 `branch.rules` |
| 12 | +- 上游变量映射位置:上游节点属性 `branch.output.mapping` |
| 13 | +- 运行时控制:记录选中的目标节点,仅放行该下游,其余直接下游跳过 |
| 14 | + |
| 15 | +## 3. 核心架构 |
| 16 | +### 3.1 元数据层 |
| 17 | +通过节点元数据表下发分支节点和相关属性,不新增分支专用业务表。 |
| 18 | + |
| 19 | +涉及元数据: |
| 20 | +- `workflow.branch` 节点定义 |
| 21 | +- `branch.rules` 节点 UI 属性 |
| 22 | +- `branch.output.mapping` 节点 UI 属性 |
| 23 | + |
| 24 | +实现位置: |
| 25 | +- `db/dss_dml.sql` |
| 26 | + |
| 27 | +### 3.2 运行时链路 |
| 28 | +1. 用户通过工作流执行接口提交流程。 |
| 29 | +2. `FlowJobNodeParser` 为每个节点创建 runner,并把共享 `flow_var_map` 注入节点参数。 |
| 30 | +3. 上游普通节点成功后,`FlowEntranceJob` 从结果集提取变量并回写到共享 `flow_var_map`。 |
| 31 | +4. 分支节点执行时,`BranchNodeRunner` 读取 `branch.rules`,计算命中的目标下游节点。 |
| 32 | +5. `FlowEntranceJob.recordBranchSelection` 记录分支节点最终选中的 target。 |
| 33 | +6. `FlowDependencyResolverImpl` 解析 pending 节点时: |
| 34 | + - 命中的直接下游转为 `scheduled` |
| 35 | + - 未命中的兄弟直接下游转为 `skipped` |
| 36 | + |
| 37 | +## 4. 关键实现类 |
| 38 | +### 4.1 执行入口 |
| 39 | +文件: |
| 40 | +- `dss-flow-execution-server/.../restful/FlowEntranceRestfulApi.java` |
| 41 | + |
| 42 | +职责: |
| 43 | +- 接收执行请求 |
| 44 | +- 提交流程到 `entranceServer` |
| 45 | + |
| 46 | +说明: |
| 47 | +- 不直接决定分支下游是否执行 |
| 48 | +- 仅是工作流执行入口 |
| 49 | + |
| 50 | +### 4.2 节点解析 |
| 51 | +文件: |
| 52 | +- `dss-flow-execution-server/.../job/parser/FlowJobNodeParser.scala` |
| 53 | + |
| 54 | +职责: |
| 55 | +- 初始化共享 `flow_var_map` |
| 56 | +- 为 `workflow.branch` 绑定 `BranchNodeRunner` |
| 57 | +- 为普通节点绑定 `DefaultNodeRunner` |
| 58 | + |
| 59 | +### 4.3 变量收集 |
| 60 | +文件: |
| 61 | +- `dss-flow-execution-server/.../job/FlowEntranceJob.scala` |
| 62 | + |
| 63 | +职责: |
| 64 | +- 在上游节点成功后采集输出变量 |
| 65 | +- 支持读取上游结果集变量 |
| 66 | +- 支持 `branch.output.mapping` 映射别名 |
| 67 | + |
| 68 | +### 4.4 规则解析 |
| 69 | +文件: |
| 70 | +- `dss-flow-execution-server/.../utils/BranchExpressionUtils.scala` |
| 71 | + |
| 72 | +职责: |
| 73 | +- 判断节点是否为分支节点 |
| 74 | +- 读取 `branch.rules` |
| 75 | +- 将规则文本解析为 `condition -> targetName` |
| 76 | +- 计算条件表达式 |
| 77 | + |
| 78 | +当前规则: |
| 79 | +- 多行规则 |
| 80 | +- 按顺序匹配 |
| 81 | +- 支持默认规则关键字:`default`、`else`、`*` |
| 82 | + |
| 83 | +### 4.5 分支节点执行 |
| 84 | +文件: |
| 85 | +- `dss-flow-execution-server/.../node/BranchNodeRunner.scala` |
| 86 | + |
| 87 | +职责: |
| 88 | +- 读取共享变量上下文 |
| 89 | +- 解析并执行 `branch.rules` |
| 90 | +- 将命中的 target 记录到 `FlowEntranceJob` |
| 91 | +- 自身不提交 Linkis 作业 |
| 92 | +- 成功后触发后续调度 |
| 93 | + |
| 94 | +### 4.6 下游节点放行与跳过 |
| 95 | +文件: |
| 96 | +- `dss-flow-execution-server/.../resolver/FlowDependencyResolverImpl.scala` |
| 97 | + |
| 98 | +职责: |
| 99 | +- 判断某个 pending 节点是否是分支命中的 target |
| 100 | +- 命中则 `scheduled` |
| 101 | +- 未命中则 `skipped` |
| 102 | + |
| 103 | +这是“控制下游节点要不要执行”的真正实现位置。 |
| 104 | + |
| 105 | +### 4.7 保存校验 |
| 106 | +文件: |
| 107 | +- `dss-workflow-server/.../service/impl/DSSFlowServiceImpl.java` |
| 108 | + |
| 109 | +职责: |
| 110 | +- 保存工作流时校验分支节点配置 |
| 111 | + |
| 112 | +校验规则: |
| 113 | +- 至少两条直接出边 |
| 114 | +- `branch.rules` 非空 |
| 115 | +- 规则中的目标节点名必须是直接下游节点名 |
| 116 | + |
| 117 | +## 5. 规则语法 |
| 118 | +### 5.1 基本格式 |
| 119 | +```text |
| 120 | +条件=下游节点名 |
| 121 | +``` |
| 122 | + |
| 123 | +### 5.2 示例 |
| 124 | +```text |
| 125 | +amount>100=节点A |
| 126 | +amount<10=节点B |
| 127 | +default=节点C |
| 128 | +``` |
| 129 | + |
| 130 | +### 5.3 语义 |
| 131 | +- 条件成立时,选择右侧节点名对应的直接下游节点 |
| 132 | +- 默认规则在前面所有规则都未命中时生效 |
| 133 | +- 若无规则命中且无默认规则,则抛异常 |
| 134 | + |
| 135 | +## 6. 变量模型 |
| 136 | +### 6.1 共享变量 |
| 137 | +共享变量保存在 `flow_var_map`。 |
| 138 | + |
| 139 | +来源包括: |
| 140 | +- 工作流全局属性 |
| 141 | +- 工作流启动参数 |
| 142 | +- 上游节点结果集变量 |
| 143 | +- `branch.output.mapping` 映射后的别名变量 |
| 144 | + |
| 145 | +### 6.2 上游结果集约束 |
| 146 | +当前版本主要支持: |
| 147 | +- 单结果集 |
| 148 | +- 简单列名到值的映射 |
| 149 | + |
| 150 | +建议上游输出示例: |
| 151 | +```sql |
| 152 | +select sum(price) as amount from order_info |
| 153 | +``` |
| 154 | + |
| 155 | +## 7. 前端设计 |
| 156 | +当前版本前端以节点属性表单为主,不再以边配置为主。 |
| 157 | + |
| 158 | +用户操作方式: |
| 159 | +1. 拖入分支节点 |
| 160 | +2. 连出多个下游节点 |
| 161 | +3. 在节点属性中填写 `branch.rules` |
| 162 | +4. 保存并执行 |
| 163 | + |
| 164 | +说明: |
| 165 | +- 分支规则配置入口应放在分支节点属性面板中 |
| 166 | +- 不要求边级条件配置弹窗作为正式入口 |
| 167 | + |
| 168 | +## 8. 非目标设计 |
| 169 | +以下方案已废弃: |
| 170 | +- `dss_workflow_branch` 表 |
| 171 | +- `BranchNodeService` |
| 172 | +- `BranchNodeMapper` |
| 173 | +- `BranchNodeConfig` 独立实体 |
| 174 | +- `POST/PUT/GET /workflow/node/branch/...` 配置接口 |
| 175 | +- `SpEL` 复杂逻辑引擎依赖 |
| 176 | +- `BranchNodeSkipStrategy` 独立跳过策略实现 |
| 177 | + |
| 178 | +## 9. 兼容性 |
| 179 | +- 不含分支节点的现有工作流执行逻辑不变 |
| 180 | +- 分支节点仅影响自身直接下游 |
| 181 | +- 旧版边条件配置不作为正式能力保留 |
| 182 | + |
| 183 | +## 10. 验证要点 |
| 184 | +- 分支节点必须能读取上游变量 |
| 185 | +- 规则文本必须正确映射到直接下游节点名 |
| 186 | +- 命中的 target 会执行 |
| 187 | +- 同级未命中的 target 会跳过 |
| 188 | +- 无命中且无默认规则时报错 |
0 commit comments