use anyhow::Result;
use async_trait::async_trait;
use crate::workflow::context::WorkflowContext;
use crate::workflow::def::NodeDef;
use crate::workflow::rule_engine::evaluate_expression;
use crate::workflow::template::TemplateRenderer;
use super::node_executor::NodeExecutor;
pub struct ConditionExecutor {
template_renderer: TemplateRenderer,
}
impl ConditionExecutor {
pub fn new() -> Self {
Self {
template_renderer: TemplateRenderer::new(),
}
}
}
impl Default for ConditionExecutor {
fn default() -> Self {
Self::new()
}
}
#[async_trait]
impl NodeExecutor for ConditionExecutor {
async fn execute(
&self,
node: &NodeDef,
context: &mut WorkflowContext,
) -> Result<serde_json::Value> {
let branches = node.branches.as_ref()
.ok_or_else(|| anyhow::anyhow!("Condition node '{}' has no branches", node.id))?;
for branch in branches {
let rendered_condition = self.template_renderer
.render(&branch.condition, &context.variables)?;
let passed = evaluate_expression(&rendered_condition, &context.variables)?;
if passed {
return Ok(serde_json::json!({
"matched_branch": branch.name,
"target": branch.target,
"condition": branch.condition,
}));
}
}
Ok(serde_json::json!({
"matched": false,
"branches_checked": branches.len(),
}))
}
fn name(&self) -> &str {
"condition_executor"
}
}