matrixcode_core/workflow/executors/
condition.rs1use anyhow::Result;
6use async_trait::async_trait;
7
8use crate::workflow::context::WorkflowContext;
9use crate::workflow::def::NodeDef;
10use crate::workflow::rule_engine::evaluate_expression;
11use crate::workflow::template::TemplateRenderer;
12use super::node_executor::NodeExecutor;
13
14pub struct ConditionExecutor {
18 template_renderer: TemplateRenderer,
20}
21
22impl ConditionExecutor {
23 pub fn new() -> Self {
25 Self {
26 template_renderer: TemplateRenderer::new(),
27 }
28 }
29}
30
31impl Default for ConditionExecutor {
32 fn default() -> Self {
33 Self::new()
34 }
35}
36
37#[async_trait]
38impl NodeExecutor for ConditionExecutor {
39 async fn execute(
40 &self,
41 node: &NodeDef,
42 context: &mut WorkflowContext,
43 ) -> Result<serde_json::Value> {
44 let branches = node.branches.as_ref()
46 .ok_or_else(|| anyhow::anyhow!("Condition node '{}' has no branches", node.id))?;
47
48 for branch in branches {
50 let rendered_condition = self.template_renderer
52 .render(&branch.condition, &context.variables)?;
53
54 let passed = evaluate_expression(&rendered_condition, &context.variables)?;
56
57 if passed {
58 return Ok(serde_json::json!({
60 "matched_branch": branch.name,
61 "target": branch.target,
62 "condition": branch.condition,
63 }));
64 }
65 }
66
67 Ok(serde_json::json!({
69 "matched": false,
70 "branches_checked": branches.len(),
71 }))
72 }
73
74 fn name(&self) -> &str {
75 "condition_executor"
76 }
77}