execution_engine/
node.rs

1//! The interface for running a node
2//!
3//! All Nodes are cast to concrete types, with each type defining it's custom execution behaviour but
4//! each type inherits from a common interface, the [`Node`](self::Node) trait.
5//!
6//! The Node trait allows us to pass around a trait object meaning we don't need knowledge of a Node's
7//! specific type, only it's behaviour.
8
9use crate::workflow;
10use async_trait::async_trait;
11use std::fmt::Debug;
12use thiserror::Error;
13
14use super::workflow::WorkflowNodeType;
15
16pub mod types;
17
18/// The error type used for defining an exception when running a node
19#[derive(Error, Debug)]
20pub enum NodeError {
21    #[error("Failed - {0}")]
22    Failed(String),
23    #[error("Communications")]
24    Communication,
25}
26
27/// The Node trait is to be implemented by all node types that can occur in a workflow
28///
29/// The Node trait is designed to be used as a trait object which allow us to erase (type erasure) the concrete
30/// type and instead rely on the methods solely available through this trait.
31#[async_trait]
32pub trait Node: Debug + Send + Sync {
33    /// Return the type of node, this is used for easily locating the Start and End nodes
34    fn kind(&self) -> WorkflowNodeType;
35    /// The current node ID, used by the [`Job`](crate::workflow::Job) struct to know the current node
36    fn id(&self) -> &str;
37    /// A pointer to the current nodes position in the [`Job.nodes`](crate::workflow::Job.nodes) collection
38    fn position(&self) -> usize;
39    /// The instructions for how to execute each node
40    async fn execute(&self) -> Result<Vec<workflow::Parameter>, NodeError> {
41        Ok(vec![])
42    }
43    /// Create message to be sent to the executor once the node has been executed
44    async fn create_msg(&self) -> workflow::Message {
45        match self.execute().await {
46            Ok(context) => workflow::Message {
47                pointer: self.position(),
48                status: workflow::NodeStatus::Success,
49                context,
50            },
51            Err(e) => workflow::Message {
52                pointer: self.position(),
53                status: workflow::NodeStatus::Failed,
54                context: vec![],
55            },
56        }
57    }
58    /// The publicly exposed API for running a node
59    async fn run(&self) -> Result<(), NodeError>;
60}