1use std::sync::Arc;
29
30use async_trait::async_trait;
31
32use crate::error::GraphError;
33use crate::execution_engine::ExecutionEngine;
34pub use crate::node_context::LeafContext;
35use crate::node_context::NodeContext;
36use crate::state::{State, StateMerge};
37use crate::workflow_state::{MergeStrategy, WorkflowState};
38
39pub use crate::barrier_node::{BarrierDefaultAction, BarrierNode};
42pub use crate::parallel_node::{ParallelErrorStrategy, ParallelNode, ParallelNodeBuilder};
43
44#[async_trait]
61pub trait LeafNode<S: WorkflowState = State>: Send + Sync {
62 async fn execute(&self, ctx: &mut LeafContext<'_, S>) -> Result<(), GraphError>;
64}
65
66#[async_trait]
76pub trait ExecutorOperation<S: WorkflowState = State>: Send + Sync {
77 async fn execute(&self, engine: &mut ExecutionEngine<S>) -> Result<(), GraphError>;
79}
80
81#[async_trait]
88pub trait FlowNode<S: WorkflowState = State>: Send + Sync {
89 async fn execute(&self, ctx: &mut NodeContext<'_, S>) -> Result<(), GraphError>;
91}
92
93pub enum NodeKind<S: WorkflowState = State, M: MergeStrategy<S> = StateMerge> {
105 Task(TaskNode<S>),
107 Condition(ConditionNode<S>),
109 Barrier(BarrierNode<S>),
111 Parallel(ParallelNode<S, M>),
113 External(Arc<dyn FlowNode<S>>),
115 ExternalLeaf(Arc<dyn LeafNode<S>>),
117}
118
119impl<S: WorkflowState, M: MergeStrategy<S>> Clone for NodeKind<S, M> {
120 fn clone(&self) -> Self {
121 match self {
122 Self::Task(n) => Self::Task(n.clone()),
123 Self::Condition(n) => Self::Condition(n.clone()),
124 Self::Barrier(n) => Self::Barrier(n.clone()),
125 Self::Parallel(n) => Self::Parallel(n.clone()),
126 Self::External(n) => Self::External(n.clone()),
127 Self::ExternalLeaf(n) => Self::ExternalLeaf(n.clone()),
128 }
129 }
130}
131
132pub type TaskFn<S> = Arc<dyn Fn(&mut NodeContext<'_, S>) -> Result<(), GraphError> + Send + Sync>;
136
137#[derive(Clone)]
139pub struct TaskNode<S: WorkflowState = State> {
140 pub name: String,
141 pub func: TaskFn<S>,
142}
143
144impl<S: WorkflowState> TaskNode<S> {
145 pub fn new(
146 name: impl Into<String>,
147 func: impl Fn(&mut NodeContext<'_, S>) -> Result<(), GraphError> + Send + Sync + 'static,
148 ) -> Self {
149 Self {
150 name: name.into(),
151 func: Arc::new(func),
152 }
153 }
154}
155
156#[async_trait]
160impl<S: WorkflowState> FlowNode<S> for TaskNode<S> {
161 async fn execute(&self, ctx: &mut NodeContext<'_, S>) -> Result<(), GraphError> {
162 (self.func)(ctx)
163 }
164}
165
166pub type BranchCondition<S> = Arc<dyn Fn(&S) -> bool + Send + Sync>;
170
171#[derive(Clone)]
173pub struct ConditionNode<S: WorkflowState = State> {
174 pub name: String,
175 pub branches: Vec<(String, BranchCondition<S>)>,
176}
177
178impl<S: WorkflowState> ConditionNode<S> {
179 pub fn builder(name: impl Into<String>) -> ConditionNodeBuilder<S> {
180 ConditionNodeBuilder {
181 name: name.into(),
182 branches: Vec::new(),
183 }
184 }
185}
186
187pub struct ConditionNodeBuilder<S: WorkflowState = State> {
189 name: String,
190 branches: Vec<(String, BranchCondition<S>)>,
191}
192
193impl<S: WorkflowState> ConditionNodeBuilder<S> {
194 pub fn branch(
195 mut self,
196 target: impl Into<String>,
197 condition: impl Fn(&S) -> bool + Send + Sync + 'static,
198 ) -> Self {
199 self.branches.push((target.into(), Arc::new(condition)));
200 self
201 }
202
203 pub fn build(self) -> ConditionNode<S> {
204 ConditionNode {
205 name: self.name,
206 branches: self.branches,
207 }
208 }
209}
210
211#[async_trait]
213impl<S: WorkflowState> LeafNode<S> for ConditionNode<S> {
214 async fn execute(&self, ctx: &mut LeafContext<'_, S>) -> Result<(), GraphError> {
215 let state = ctx.state();
216 for (target, condition) in &self.branches {
217 if condition(state) {
218 ctx.goto(target);
219 return Ok(());
220 }
221 }
222 Ok(())
223 }
224}
225
226#[async_trait]
228impl<S: WorkflowState> FlowNode<S> for ConditionNode<S> {
229 async fn execute(&self, ctx: &mut NodeContext<'_, S>) -> Result<(), GraphError> {
230 let state = ctx.state();
231 for (target, condition) in &self.branches {
232 if condition(state) {
233 ctx.goto(target);
234 return Ok(());
235 }
236 }
237 Ok(())
238 }
239}
240
241pub type GraphNode<S> = dyn FlowNode<S>;