Skip to main content

ri_agent_graph/
executor.rs

1//! Executor abstraction for running node attempts.
2//!
3//! The [`Executor`] trait allows plugging in different execution strategies
4//! (in-process, external job queue, etc.) without changing graph logic.
5
6use crate::command::NodeOutput;
7use crate::config::GraphConfig;
8use crate::node::Node;
9use crate::state::AgentState;
10use crate::Result;
11use std::future::Future;
12use std::pin::Pin;
13use std::sync::Arc;
14
15/// Trait for executing individual node attempts.
16///
17/// The default [`InProcessExecutor`] runs nodes directly in the current tokio runtime.
18/// Alternative implementations (e.g., tauri-queue) can be provided behind feature flags.
19///
20/// Uses boxed futures instead of async-trait.
21pub trait Executor: Send + Sync {
22    /// Execute a single node attempt.
23    ///
24    /// The executor owns the `Arc<dyn Node>`, `AgentState`, and `GraphConfig`
25    /// so the returned future is `'static` and can be spawned on a task.
26    fn execute_node(
27        &self,
28        node: Arc<dyn Node>,
29        state: AgentState,
30        config: GraphConfig,
31    ) -> Pin<Box<dyn Future<Output = Result<NodeOutput>> + Send>>;
32}
33
34/// Default executor: runs nodes directly in the current tokio runtime.
35pub struct InProcessExecutor;
36
37impl InProcessExecutor {
38    pub fn new() -> Self {
39        Self
40    }
41}
42
43impl Default for InProcessExecutor {
44    fn default() -> Self {
45        Self::new()
46    }
47}
48
49impl Executor for InProcessExecutor {
50    fn execute_node(
51        &self,
52        node: Arc<dyn Node>,
53        state: AgentState,
54        config: GraphConfig,
55    ) -> Pin<Box<dyn Future<Output = Result<NodeOutput>> + Send>> {
56        Box::pin(async move { node.execute(&state, &config).await })
57    }
58}