use std::marker::PhantomData;
use async_trait::async_trait;
use crate::saga::ActionComputation;
#[async_trait]
pub trait ActionPublisher<A, Error> {
async fn publish(&self, action: &[A]) -> Result<Vec<A>, Error>;
}
pub struct SagaManager<A, AR, Publisher, Saga, Error>
where
Publisher: ActionPublisher<A, Error>,
Saga: ActionComputation<AR, A>,
{
action_publisher: Publisher,
saga: Saga,
_marker: PhantomData<(A, AR, Error)>,
}
impl<A, AR, Publisher, Saga, Error> ActionComputation<AR, A>
for SagaManager<A, AR, Publisher, Saga, Error>
where
Publisher: ActionPublisher<A, Error>,
Saga: ActionComputation<AR, A>,
{
fn compute_new_actions(&self, action_result: &AR) -> Vec<A> {
self.saga.compute_new_actions(action_result)
}
}
#[async_trait]
impl<A, AR, Publisher, Saga, Error> ActionPublisher<A, Error>
for SagaManager<A, AR, Publisher, Saga, Error>
where
Publisher: ActionPublisher<A, Error> + Sync,
Saga: ActionComputation<AR, A> + Sync,
A: Sync,
AR: Sync,
Error: Sync,
{
async fn publish(&self, action: &[A]) -> Result<Vec<A>, Error> {
self.action_publisher.publish(action).await
}
}
impl<A, AR, Publisher, Saga, Error> SagaManager<A, AR, Publisher, Saga, Error>
where
Publisher: ActionPublisher<A, Error> + Sync,
Saga: ActionComputation<AR, A> + Sync,
A: Sync,
AR: Sync,
Error: Sync,
{
pub fn new(action_publisher: Publisher, saga: Saga) -> Self {
SagaManager {
action_publisher,
saga,
_marker: PhantomData,
}
}
pub async fn handle(&self, action_result: &AR) -> Result<Vec<A>, Error> {
let new_actions = self.compute_new_actions(action_result);
let published_actions = self.publish(&new_actions).await?;
Ok(published_actions)
}
}