3.9 KiB
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 参数,便于排查。
正面评价
- 状态机设计优秀:
is_legal转换表清晰,set_cancelled作为唯一受控旁路,设计合理 - executor 取消处理: Ok/Err 分支对称处理已取消节点,状态机与事件类型一致,TOCTOU 已修复
- EventBus broadcast 容量 256: 审批低频场景设计合理
- conditions 求值失败保守 false: 安全优先,文档清晰
- 锁中毒降级不 panic: 返回保守默认值,符合"无 panic"铁律
- 测试覆盖: state.rs 测试完整(合法/非法/克隆/取消),executor 测试在 executor_helpers.rs