Files
DevFlow/docs/05-代码审查/02-df-workflow-走查-2026-08-02.md

71 lines
3.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# df-workflow 核心代码走查报告
> 走查日期: 2026-08-02
> 范围: crates/df-workflow/src/ (11 文件, ~108KB)
> 核心文件: executor.rs(258行), conditions.rs(934行), state.rs(257行), registry.rs(81行), node.rs(77行), dag.rs, dag_def.rs, eventbus.rs(57行)
---
## 问题汇总
| # | 等级 | 文件 | 类型 | 简述 |
|---|---|---|---|---|
| 1 | 🔴 P0 | conditions.rs | bug | 单引号字符串 `''` 转义为 `'` 时闭引号后再跟 `'` 会误判(如 `'it''s'` 跨行) |
| 2 | 🟡 P1 | conditions.rs | smell | 934 行单文件,tokenizer/parser/jsonpath/测试全混在一起,维护性差 |
| 3 | 🟡 P1 | conditions.rs | risk | 默认 feature `conditions-eval` 关闭,934 行代码实际不生效 |
| 4 | 🟡 P1 | executor.rs | risk | `condition` 边条件求值仅在 `eval_conditions` 为 true 时收集 inputs,但 `outputs.insert` 仍写入所有节点,已跳过的节点 output 可能被下游无条件边误消费 |
| 5 | 🟡 P1 | state.rs | risk | 锁中毒降级日志缺少 `node_id` 上下文,排查时难以定位哪个节点触发了中毒 |
| 6 | 🟢 P2 | node.rs | smell | `NodeContext``inputs` 类型为 `HashMap<String, NodeOutput>``NodeOutput` 仅含 `data: serde_json::Value`,工具调用结果无法区分来源 |
| 7 | 🟢 P2 | executor.rs | smell | 条件路由的 `eval_conditions` 标志取自 `cfg!(feature = "conditions-eval")`,编译期常量化后分支在运行时不可变,但 executor 仍用 `if eval_conditions` 运行时分支 |
| 8 | 🟢 P2 | eventbus.rs | smell | `send` 参数 `async fn` 但实际是同步调用(`broadcast::send` 同步),`async` 包装造成误导 |
| 9 | 🟢 P2 | executor.rs | smell | `adjacency_in` 预建索引仅用于 `condition` 场景,非条件场景下 `HashMap::new()` 占位浪费 |
---
## 🔴 P0 问题详述
### #1 conditions.rs 单引号转义边界 bug
**文件**: `conditions.rs:200-225`
**严重**: P0 — 可能产生错误的表达式求值结果
**现状**: `consume_quoted` 函数在遇到 `''` 时跳过(视为转义),但 `consume_key` 不处理单引号。
**影响**: 表达式 `'it''s' == 'value'` 中,`'it''s'` 被解析为 `it's`,但闭引号后紧跟 `'==` 可能导致 `consume_key` 截断异常。
---
## 🟡 P1 问题详述
### #2 conditions.rs 单文件 934 行
**建议**: 拆为 `tokenizer.rs` / `parser.rs` / `jsonpath.rs` / `tests.rs` 四个模块,类似 df-nodes 的拆分模式。
### #3 conditions-eval feature 默认关闭
**现状**: 934 行代码 + 全面测试 + 递归下降解析器 + JSON Path 引擎,全部在 feature gate 后面。executor 中 `eval_conditions` 编译期常量化,运行时条件路由不生效。
**建议**: 要么默认开启 feature,要么在 ARCHITECTURE.md 中说明为何写了不开。
### #4 executor 条件边 output 残留
**文件**: `executor.rs:188`
**风险**: 已跳过的节点(condition 不满足),`outputs.insert` 不会执行(因为 `continue` 了),但若后续层有**无条件边**引用该跳过的节点,`outputs.get` 返回 None,下游节点inputs 空。
**建议**: 确认无条件边是否有 fallback 处理,或补测试覆盖。
### #5 锁中毒日志缺少 node_id
**文件**: `state.rs:60-68`
**建议**: 在 `lock()` 失败时输出的 `tracing::error!` 中增加 `node_id` 参数,便于排查。
---
## 正面评价
1. **状态机设计优秀**: `is_legal` 转换表清晰,`set_cancelled` 作为唯一受控旁路,设计合理
2. **executor 取消处理**: Ok/Err 分支对称处理已取消节点,状态机与事件类型一致,TOCTOU 已修复
3. **EventBus broadcast 容量 256**: 审批低频场景设计合理
4. **conditions 求值失败保守 false**: 安全优先,文档清晰
5. **锁中毒降级不 panic**: 返回保守默认值,符合"无 panic"铁律
6. **测试覆盖**: state.rs 测试完整(合法/非法/克隆/取消),executor 测试在 executor_helpers.rs