flow-graph-interpreter 0.22.0

An intepreter for flow-based programs
Documentation
use std::sync::Arc;

use flow_component::{Component, ComponentError, LocalScope};
use wick_interface_types::ComponentSignature;
use wick_packet::{Invocation, PacketStream, RuntimeConfig};

use crate::interpreter::channel::InterpreterDispatchChannel;
use crate::interpreter::executor::SchematicExecutor;
use crate::interpreter::program::ProgramState;
use crate::{BoxFuture, HandlerMap};

#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)]
pub(crate) enum Error {
  #[error("Operation '{0}' not found on this component")]
  SchematicNotFound(String),
}

#[derive(Debug)]
pub(crate) struct InnerSelf {
  signature: ComponentSignature,
  schematics: Arc<Vec<SchematicExecutor>>,
  components: Arc<HandlerMap>,
}

impl InnerSelf {
  pub(crate) fn new(
    components: Arc<HandlerMap>,
    state: &ProgramState,
    dispatcher: &InterpreterDispatchChannel,
    root_config: Option<&RuntimeConfig>,
  ) -> Self {
    let schematics: Arc<Vec<SchematicExecutor>> = Arc::new(
      state
        .network
        .schematics()
        .iter()
        .map(|s| SchematicExecutor::new(s.clone(), dispatcher.clone(), root_config.cloned()))
        .collect(),
    );
    let signature = state.components[SelfComponent::ID].clone();
    Self {
      signature,
      schematics,
      components,
    }
  }
}

#[derive(Debug, Clone)]
pub(crate) struct SelfComponent {
  inner: Arc<InnerSelf>,
}

impl SelfComponent {
  pub(crate) const ID: &str = "self";

  pub(crate) fn new(
    components: Arc<HandlerMap>,
    state: &ProgramState,
    dispatcher: &InterpreterDispatchChannel,
    root_config: Option<&RuntimeConfig>,
  ) -> Self {
    let inner_self = InnerSelf::new(components, state, dispatcher, root_config);
    Self {
      inner: Arc::new(inner_self),
    }
  }
}

impl Component for SelfComponent {
  fn handle(
    &self,
    invocation: Invocation,
    config: Option<RuntimeConfig>,
    callback: LocalScope,
  ) -> BoxFuture<Result<PacketStream, ComponentError>> {
    invocation.trace(|| debug!(target = %invocation.target(), namespace = Self::ID));

    let operation = invocation.target().operation_id().to_owned();
    let fut = self
      .inner
      .schematics
      .iter()
      .find(|s| s.name() == operation)
      .map(|s| {
        s.invoke(
          invocation,
          self.inner.components.clone(),
          self.clone(),
          config,
          callback,
        )
      })
      .ok_or_else(|| Error::SchematicNotFound(operation.clone()));

    Box::pin(async move {
      match fut {
        Ok(fut) => fut.await.map_err(ComponentError::new),
        Err(e) => Err(ComponentError::new(e)),
      }
    })
  }

  fn signature(&self) -> &ComponentSignature {
    &self.inner.signature
  }
}