use crate::exchange::{Exchange, ExchangeError};
use crate::router::path::LoadedChain;
use crate::status::ExchangeState;
use async_trait::async_trait;
use std::sync::Arc;
use thiserror::Error;
use crate::handler::Handler;
#[async_trait]
pub trait HandlerExecutor<Exchange>
where
Exchange: Send + Sync,
{
type Output: Send + Sync;
async fn execute_handler(handlers: &Vec<Arc<dyn Handler<Exchange>>>, exchange: &mut Exchange) -> Result<bool, ExecutorError>
where
Exchange: ExtractOutput<Self::Output> + Send + Sync,
{
for handler in handlers {
let status = handler.exec(exchange).await.unwrap();
if status.code.is_in_flight() {
continue;
} else if status.code.is_completed() || status.code.is_error() {
return Ok(true);
} else {
return Err(ExecutorError::unknown_exchange_state(status.code));
}
}
Ok(false)
}
async fn execute_handlers(
&self,
executables: Arc<LoadedChain<Exchange>>,
exchange: &mut Exchange,
) -> Result<Self::Output, ExecutorError>;
async fn return_output(exchange: &mut Exchange) -> Result<Self::Output, ExecutorError>;
}
#[derive(Error, Debug)]
pub enum ExecutorError {
#[error("Exchange is in an unknown state: {state}")]
State { state: ExchangeState },
#[error("Failed to extract output from exchange.")]
Output {
#[source]
source: ExchangeError,
},
}
impl ExecutorError {
pub fn output_read_error(err: ExchangeError) -> Self {
ExecutorError::Output { source: err }
}
pub fn unknown_exchange_state(state: ExchangeState) -> Self {
ExecutorError::State { state }
}
}
pub struct DefaultExecutor<Output> {
pub _phantom: std::marker::PhantomData<Output>,
}
#[async_trait]
impl<E, Output> HandlerExecutor<E> for DefaultExecutor<Output>
where
E: ExtractOutput<Output> + Send + Sync,
Output: Send + Sync,
{
type Output = Output;
async fn execute_handlers(
&self,
executables: Arc<LoadedChain<E>>,
exchange: &mut E,
) -> Result<Self::Output, ExecutorError> {
let request_handlers = executables.request_handlers();
let request_handlers_result = Self::execute_handler(&request_handlers, exchange).await?;
if request_handlers_result {
return Ok(Self::return_output(exchange).await?);
}
let termination_handler = executables.termination_handler();
let status = termination_handler.exec(exchange).await.unwrap();
if status.code.is_completed() || status.code.is_error() {
return Ok(Self::return_output(exchange).await?);
} else if !status.code.is_in_flight() {
return Err(ExecutorError::unknown_exchange_state(status.code));
}
let response_handlers = executables.response_handlers();
Self::execute_handler(&response_handlers, exchange).await?;
exchange
.extract_output()
.await
.map_err(|e| ExecutorError::output_read_error(e))
}
async fn return_output(exchange: &mut E) -> Result<Self::Output, ExecutorError> {
exchange.extract_output().await.map_err(|e| ExecutorError::output_read_error(e))
}
}
#[async_trait]
pub trait ExtractOutput<Output> {
async fn extract_output(&mut self) -> Result<Output, ExchangeError>;
}
#[async_trait]
impl<In, Out, Meta> ExtractOutput<Out> for Exchange<In, Out, Meta>
where
In: Send + Sync,
Out: Send + Sync,
Meta: Send + Sync,
{
async fn extract_output(&mut self) -> Result<Out, ExchangeError> {
self.take_output().await
}
}