use std::future::Future;
use uuid::Uuid;
use super::{Event, Sequence};
use crate::aggregate::{Aggregate, Root};
use crate::error::{self, Error};
use crate::version::SerializeVersion;
#[trait_variant::make(Send)]
pub trait Publish {
async fn publish<E>(
&mut self,
id: Uuid,
last_sequence: Sequence,
event: E,
) -> error::Result<Sequence>
where
E: Event + SerializeVersion;
}
#[trait_variant::make(Send)]
pub trait PublishExt: Publish {
async fn write<A>(&mut self, root: Root<A>, event: A::Event) -> error::Result<Root<A>>
where
A: Aggregate,
A::Event: SerializeVersion;
async fn try_write<A>(&mut self, root: Root<A>, command: A::Command) -> error::Result<Root<A>>
where
A: Aggregate,
A::Event: SerializeVersion;
}
impl<T: Publish> PublishExt for T {
async fn write<A>(&mut self, root: Root<A>, event: A::Event) -> error::Result<Root<A>>
where
A: Aggregate,
A::Event: SerializeVersion,
{
let id = Root::id(&root);
let last_sequence = Root::last_sequence(&root);
let aggregate = Root::into_inner(root).apply(&event);
self.publish::<A::Event>(id, last_sequence, event).await?;
Ok(Root::with_aggregate(aggregate, id, last_sequence))
}
fn try_write<A>(
&mut self,
root: Root<A>,
command: A::Command,
) -> impl Future<Output = error::Result<Root<A>>>
where
A: Aggregate,
A::Event: SerializeVersion,
{
let event = root.process(command).map_err(|e| Error::External(e.into()));
async move { self.write(root, event?).await }
}
}