use async_trait::async_trait;
use indexmap::IndexMap;
use super::{
BspContext,
error::BspError,
graph::{NodeId, PortIndex},
recovery::RecoveryPolicy,
run::RunContext,
value::BspValue,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Activation {
#[default]
Any,
All,
}
#[derive(Debug)]
pub enum NodeOutcome {
Success(IndexMap<PortIndex, BspValue>),
Suspend {
payload: serde_json::Value,
waiting_inputs: Vec<PortIndex>,
},
}
#[async_trait]
pub trait BspNode<S>: Send + Sync {
fn name(&self) -> &str;
fn type_name(&self) -> &str {
self.name()
}
fn input_ports(&self) -> Vec<PortIndex> {
Vec::new()
}
fn output_ports(&self) -> Vec<PortIndex> {
Vec::new()
}
fn is_dynamic_output(&self) -> bool {
false
}
fn activation(&self) -> Activation {
Activation::Any
}
fn recovery(&self) -> RecoveryPolicy {
RecoveryPolicy::FailFast
}
fn merger(&self) -> Option<&str> {
None
}
fn max_executions(&self) -> Option<u64> {
None
}
async fn execute(&self, run: &mut RunContext<'_, S>) -> Result<NodeOutcome, BspError>;
}
#[async_trait]
impl<S: Send> BspNode<S> for Box<dyn BspNode<S>> {
fn name(&self) -> &str {
(**self).name()
}
fn type_name(&self) -> &str {
(**self).type_name()
}
fn input_ports(&self) -> Vec<PortIndex> {
(**self).input_ports()
}
fn output_ports(&self) -> Vec<PortIndex> {
(**self).output_ports()
}
fn is_dynamic_output(&self) -> bool {
(**self).is_dynamic_output()
}
fn activation(&self) -> Activation {
(**self).activation()
}
fn recovery(&self) -> RecoveryPolicy {
(**self).recovery()
}
fn merger(&self) -> Option<&str> {
(**self).merger()
}
fn max_executions(&self) -> Option<u64> {
(**self).max_executions()
}
async fn execute(&self, run: &mut RunContext<'_, S>) -> Result<NodeOutcome, BspError> {
(**self).execute(run).await
}
}
#[async_trait]
pub trait DataflowNode: Send + Sync {
fn name(&self) -> &str;
fn input_ports(&self) -> Vec<PortIndex>;
fn output_ports(&self) -> Vec<PortIndex>;
fn is_dynamic_output(&self) -> bool {
false
}
async fn execute(
&self,
node_id: NodeId,
inputs: IndexMap<PortIndex, BspValue>,
ctx: &BspContext,
) -> Result<IndexMap<PortIndex, BspValue>, BspError>;
}
#[async_trait]
impl<S: Send, T: DataflowNode> BspNode<S> for T {
fn name(&self) -> &str {
DataflowNode::name(self)
}
fn type_name(&self) -> &str {
DataflowNode::name(self)
}
fn input_ports(&self) -> Vec<PortIndex> {
DataflowNode::input_ports(self)
}
fn output_ports(&self) -> Vec<PortIndex> {
DataflowNode::output_ports(self)
}
fn is_dynamic_output(&self) -> bool {
DataflowNode::is_dynamic_output(self)
}
fn activation(&self) -> Activation {
Activation::All
}
async fn execute(&self, run: &mut RunContext<'_, S>) -> Result<NodeOutcome, BspError> {
let inputs = std::mem::take(&mut run.inputs);
let outputs = DataflowNode::execute(self, run.node_id, inputs, run.ctx).await?;
Ok(NodeOutcome::Success(outputs))
}
}