Skip to content

Conversation

@leavesster
Copy link
Contributor

No description provided.

Copilot AI review requested due to automatic review settings September 26, 2025 02:48
@coderabbitai
Copy link

coderabbitai bot commented Sep 26, 2025

Summary by CodeRabbit

  • 新功能
    • 支持在清单/工作流中定义“Fallback”后备节点,解析器可识别并正确解析该节点类型。默认并发、输入与忽略/不触发策略已内建,提升流程健壮性与可预期性。
  • 测试
    • 新增对 YAML 中 Fallback 节点解析的单元测试,以及包含多种节点类型(含 Fallback)的序列解析测试,提升解析可靠性。

Walkthrough

在节点定义文件中新增 Fallback 节点类型,作为 Node 枚举的新变体 FallBack。更新相关行为以识别该变体,并新增针对 YAML 解析的单元测试,包括解析单个 Fallback 节点与包含 FallBack 的节点序列。

Changes

Cohort / File(s) Change Summary
节点定义与解析
manifest_reader/src/manifest/node/definition.rs
新增公共结构体 FallbackNode(含字段 node_id,使用私有 helper 进行 serde 默认值);在公共枚举 Node 中加入新变体 FallBack(FallbackNode);扩展相关行为以支持 FallBack:node_id 返回其 node_id、并发度使用 default_concurrencyinputs_from 返回 Noneshould_ignore 为真、should_spawn 为假;新增测试模块,覆盖从 YAML 解析 FallbackNode 以及包含 FallBack 的节点序列解析。

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Pre-merge checks

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description Check ❓ Inconclusive 该 PR 完全没有提供描述,未包含任何与变更集相关的上下文或说明,因而无法帮助审查者理解变更目标。 请补充一个概述性描述,说明新增 FallbackNode 及相关行为修改的目的和使用场景。
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed PR 标题采用了符合规范的 <type>: <subject> 格式,使用英文且直接描述了新增节点回退功能,准确反映了主要变更内容。

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a new FallbackNode type to the node system, extending the existing node enumeration with fallback functionality. The implementation provides a default node ID of "fallback" and integrates the new node type across all existing node operations.

  • Introduces FallbackNode struct with default node ID functionality
  • Extends the Node enum to include the new FallBack variant
  • Updates all node methods to handle the fallback case with appropriate default behaviors

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
manifest_reader/src/manifest/node/definition.rs (1)

22-32: 在 manifest_meta/src/node/definition.rs 中补齐 Fallback 变体及匹配分支

manifest_meta 的 Node 枚举缺少 FallBack(FallbackNode) 变体及相应的匹配分支(如 node_id、concurrency、inputs_from、ignore 等),请同步添加以保持与 manifest_reader 一致。

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fe01a0e and 7b2db39.

📒 Files selected for processing (1)
  • manifest_reader/src/manifest/node/definition.rs (7 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
manifest_reader/src/manifest/node/definition.rs (2)
manifest_reader/src/manifest/node/common.rs (1)
  • default_concurrency (23-25)
manifest_meta/src/node/definition.rs (1)
  • node_id (51-59)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: rust-test
  • GitHub Check: rust-test
🔇 Additional comments (1)
manifest_reader/src/manifest/node/definition.rs (1)

47-57: 行为定义 LGTM

  • concurrency: Fallback 默认并发=1,合理。
  • should_ignore: Fallback 恒为 true,符合“只用于分支控制,不参与执行”的预期。
  • should_spawn: Fallback 恒为 false,合理。

Also applies to: 69-79, 81-94

Comment on lines +12 to +16
#[derive(Deserialize, Debug, Clone)]
pub struct FallbackNode {
#[serde(default = "fallback_node_id")]
pub node_id: NodeId,
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

修复:untagged 变体充当“吞掉一切”的兜底,导致任意 YAML 条目都会被反序列化为 Fallback

当前 FallbackNode 只有一个带默认值的字段,且未拒绝未知字段。配合 #[serde(untagged)],它会匹配几乎任何映射(例如测试里的 comment: ...),从而静默吞掉拼写错误/未知节点,削弱配置校验,并改变现有变体的匹配优先级。必须要求出现显式的 fallback 键,且拒绝未知字段,避免误匹配。

建议修改如下:

-#[derive(Deserialize, Debug, Clone)]
-pub struct FallbackNode {
-    #[serde(default = "fallback_node_id")]
-    pub node_id: NodeId,
-}
+#[derive(Deserialize, Debug, Clone)]
+#[serde(deny_unknown_fields)]
+pub struct FallbackNode {
+    // 要求存在 `fallback` 键,以免该变体在 untagged 下成为“捕获所有”
+    pub fallback: serde::de::IgnoredAny,
+    #[serde(default = "fallback_node_id")]
+    pub node_id: NodeId,
+}

Also applies to: 18-20

Service(ServiceNode),
Condition(ConditionNode),
Value(ValueNode),
FallBack(FallbackNode),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

命名一致性:将枚举变体从 FallBack 重命名为 Fallback

现有命名与其它变体(Task/Subflow/Service/...)不一致。该变体是新公开 API,建议立即更正,避免之后的 API 震荡。

-    FallBack(FallbackNode),
+    Fallback(FallbackNode),
@@
-            Node::FallBack(fallback) => &fallback.node_id,
+            Node::Fallback(fallback) => &fallback.node_id,
@@
-            Node::FallBack(_fallback) => default_concurrency(),
+            Node::Fallback(_fallback) => default_concurrency(),
@@
-            Node::FallBack(_) => None,
+            Node::Fallback(_) => None,
@@
-            Node::FallBack(_) => true,
+            Node::Fallback(_) => true,
@@
-            Node::FallBack(_) => false,
+            Node::Fallback(_) => false,

Also applies to: 43-43, 55-55, 66-66, 77-77, 92-92

🤖 Prompt for AI Agents
In manifest_reader/src/manifest/node/definition.rs around lines 31, 43, 55, 66,
77 and 92, the enum variant is named "FallBack" which is inconsistent with other
variants and public API; rename the variant to "Fallback" everywhere it appears
(declaration and all usages), update any pattern matches, constructors, and
documentation/comments to use the corrected spelling, and run cargo check/tests
to ensure no remaining references to the old "FallBack" identifier remain.

Comment on lines +97 to +111
#[cfg(test)]
mod tests {
use super::*;
use serde_yaml;

#[test]
fn test_fallback_node() {
let yaml = r#"
a: c
"#;

let node: FallbackNode = serde_yaml::from_str(yaml).unwrap();
assert_eq!(node.node_id, NodeId::from("fallback".to_owned()));
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

测试用例应要求显式的 fallback 键,避免误匹配

当前用 a: c 也能反序列化为 FallbackNode,恰好暴露了“吞掉一切”的问题。建议改成要求出现 fallback 键的形状。

-        let yaml = r#"
-        a: c
-        "#;
+        let yaml = r#"
+        fallback: {}
+        "#;
🤖 Prompt for AI Agents
In manifest_reader/src/manifest/node/definition.rs around lines 97 to 111, the
FallbackNode test and current deserialization accept any mapping (e.g., `a: c`)
which masks a lax Deserialize implementation; change the deserialization to
require an explicit top-level `fallback` key (either by adjusting the struct to
have a `fallback` field or implementing custom Deserialize that errors when the
`fallback` key is missing), update the test YAML to include the `fallback:` key
with the appropriate value, and add/adjust tests to ensure deserialization fails
for mappings that do not contain `fallback`.

Comment on lines +112 to +149
#[test]
fn test_nodes() {
let yaml = r#"
- task: example_task
node_id: example_node
inputs_from:
- handle: input_handle
value: null
concurrency: 5
ignore: false
- slot: example_slot
node_id: slot_node
- service: example_service
node_id: service_node
- condition:
handle: condition_handle
node_id: condition_node
- value:
key: example_key
value: example_value
node_id: value_node
- fallback:
node_id: fallback_node
- comment: This is a comment and should be ignored
"#;

let nodes: Vec<Node> = serde_yaml::from_str(yaml).unwrap();
assert_eq!(nodes.len(), 7);
assert_eq!(nodes[0].node_id(), &NodeId::from("example_node".to_owned()));
assert_eq!(nodes[1].node_id(), &NodeId::from("slot_node".to_owned()));
assert_eq!(nodes[2].node_id(), &NodeId::from("service_node".to_owned()));
assert_eq!(
nodes[3].node_id(),
&NodeId::from("condition_node".to_owned())
);
assert_eq!(nodes[4].node_id(), &NodeId::from("value_node".to_owned()));
assert_eq!(nodes[5].node_id(), &NodeId::from("fallback".to_owned()));
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

YAML 形状不一致且隐藏配置错误:fallback 的 node_id 放在嵌套层里,且“comment”被吞掉

  • 其它节点的 node_id 在顶层;fallback 却把 node_id 放在嵌套的 fallback: 下,导致该值被丢弃,进而使用默认 fallback,与直觉不符。
  • “comment” 项本不应作为 Node 被接受;当前实现会被 Fallback 吞掉。建议去掉该条,或定义专门的 Comment 变体/预处理逻辑明确忽略。

建议统一形状并修复断言:

-        - fallback:
-            node_id: fallback_node
-        - comment: This is a comment and should be ignored
+        - fallback: {}
+          node_id: fallback_node
@@
-        assert_eq!(nodes.len(), 7);
+        assert_eq!(nodes.len(), 6);
@@
-        assert_eq!(nodes[5].node_id(), &NodeId::from("fallback".to_owned()));
+        assert_eq!(nodes[5].node_id(), &NodeId::from("fallback_node".to_owned()));
🤖 Prompt for AI Agents
In manifest_reader/src/manifest/node/definition.rs around lines 112 to 149, the
test YAML mixes shapes: most nodes put node_id at top-level but the fallback
node nests node_id under "fallback", and a raw "comment" entry is being parsed
as a Node; update the test YAML so every node has node_id at the top level (move
the fallback's node_id out of the nested map) and remove the "comment" entry (or
replace it with an explicit comment line) so it is not parsed as a Node, then
adjust the expected nodes.len() and subsequent assertions to match the corrected
7-node structure and the correct node_id strings (e.g., fallback node_id should
be "fallback_node" if you rename it consistently).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants