use async_trait::async_trait;
use serde_json::Value;
use crate::pipeline::PipelineError;
use crate::pipeline::model::ExecutionBus;
#[derive(Debug, Clone)]
pub struct NodeExecutionInput {
pub node_id: String,
pub input_pin: String,
pub payload: Value,
pub metadata: Value,
pub bus: Option<std::sync::Arc<ExecutionBus>>,
}
#[derive(Debug, Clone)]
pub struct NodeExecutionOutput {
pub output_pins: Vec<String>,
pub payload: Value,
pub trace: Vec<String>,
}
#[async_trait]
pub trait NodeHandler: Send + Sync {
fn kind(&self) -> &'static str;
fn input_pins(&self) -> &'static [&'static str];
fn output_pins(&self) -> &'static [&'static str];
async fn execute_async(
&self,
input: NodeExecutionInput,
) -> Result<NodeExecutionOutput, PipelineError>;
async fn execute_many_async(
&self,
input: NodeExecutionInput,
) -> Result<Vec<NodeExecutionOutput>, PipelineError> {
Ok(vec![self.execute_async(input).await?])
}
fn execute(&self, input: NodeExecutionInput) -> Result<NodeExecutionOutput, PipelineError> {
if tokio::runtime::Handle::try_current().is_ok() {
return Err(PipelineError::new(
"FW_NODE_SYNC_IN_ASYNC",
"synchronous NodeHandler::execute used inside async runtime; call execute_async instead",
));
}
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.map_err(|err| PipelineError::new("FW_NODE_RUNTIME", err.to_string()))?;
runtime.block_on(self.execute_async(input))
}
}