Skip to main content

juncture_core/node/
trait.rs

1use crate::{State, command::Command, config::RunnableConfig, error::JunctureError};
2
3/// Node trait for graph execution
4///
5/// A node represents a unit of work in a Juncture graph. Nodes receive
6/// an owned state snapshot and return a command indicating how to update
7/// the state and where to route next.
8///
9/// # Examples
10///
11/// ```ignore
12/// use juncture_core::{State, Node, Command, RunnableConfig};
13/// use std::future::Ready;
14/// use std::pin::Pin;
15///
16/// struct MyState;
17/// impl State for MyState {
18///     type Update = MyStateUpdate;
19/// }
20///
21/// struct MyStateUpdate;
22///
23/// struct MyNode;
24///
25/// impl Node<MyState> for MyNode {
26///     fn call(
27///         &self,
28///         state: MyState,
29///         config: &RunnableConfig,
30///     ) -> Pin<Box<dyn std::future::Future<Output = Result<Command<MyState>, JunctureError>> + '_>> {
31///         Box::pin(async move {
32///             Ok(Command::end())
33///         })
34///     }
35///
36///     fn name(&self) -> &str {
37///         "my_node"
38///     }
39/// }
40/// ```
41pub trait Node<S: State>: Send + Sync + 'static {
42    /// Execute the node logic
43    ///
44    /// Receives a shared state reference and configuration, returns a command
45    /// indicating state updates and routing decisions.
46    ///
47    /// # Errors
48    ///
49    /// Returns a [`JunctureError`] if node execution fails. The error will be
50    /// propagated to error handlers if configured.
51    fn call(
52        &self,
53        state: &S,
54        config: &RunnableConfig,
55    ) -> std::pin::Pin<
56        Box<dyn std::future::Future<Output = Result<Command<S>, JunctureError>> + Send + '_>,
57    >;
58
59    /// Execute node logic with `Arc<S>` to avoid O(N) state clone.
60    ///
61    /// When the caller already holds `Arc<S>` (e.g., the Pregel runner), this
62    /// method avoids the `O(state_size)` clone that `call()` requires for lifetime
63    /// extension into async blocks. The default implementation delegates to
64    /// [`call`](Self::call), which still clones. Wrapper types override this to
65    /// use O(1) `Arc::clone` instead.
66    ///
67    /// # Errors
68    ///
69    /// Returns a [`JunctureError`] if node execution fails.
70    fn call_arc(
71        &self,
72        state: std::sync::Arc<S>,
73        config: &RunnableConfig,
74    ) -> std::pin::Pin<
75        Box<dyn std::future::Future<Output = Result<Command<S>, JunctureError>> + Send + '_>,
76    > {
77        self.call(&state, config)
78    }
79
80    /// Get the node name
81    ///
82    /// Returns the node's identifier used for logging, tracing, and error messages.
83    fn name(&self) -> &str;
84}
85
86// Rust guideline compliant 2025-01-18