matrixcode_core/workflow/executors/
condition.rs1use anyhow::Result;
6use async_trait::async_trait;
7
8use super::node_executor::NodeExecutor;
9use crate::workflow::context::WorkflowContext;
10use crate::workflow::def::NodeDef;
11use crate::workflow::rule_engine::evaluate_expression;
12use crate::workflow::template::TemplateRenderer;
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
46 .branches
47 .as_ref()
48 .ok_or_else(|| anyhow::anyhow!("Condition node '{}' has no branches", node.id))?;
49
50 for branch in branches {
52 let rendered_condition = self
54 .template_renderer
55 .render(&branch.condition, &context.variables)?;
56
57 let passed = evaluate_expression(&rendered_condition, &context.variables)?;
59
60 if passed {
61 return Ok(serde_json::json!({
63 "matched_branch": branch.name,
64 "target": branch.target,
65 "condition": branch.condition,
66 }));
67 }
68 }
69
70 Ok(serde_json::json!({
72 "matched": false,
73 "branches_checked": branches.len(),
74 }))
75 }
76
77 fn name(&self) -> &str {
78 "condition_executor"
79 }
80}