use crate::errors::UniError;
use ahash::AHashSet;
use rkyv::{
Archive, Deserialize, Serialize,
api::high::to_bytes_with_alloc,
de::Pool,
rancor::{Error, Strategy},
ser::{
Serializer,
allocator::{Arena, ArenaHandle},
sharing::Share,
},
util::AlignedVec,
};
use std::future::Future;
use uuid::Uuid;
pub trait Aggregate: Send + Clone + 'static {
fn new(id: Uuid) -> Self;
fn next(&mut self);
fn id(&self) -> Uuid;
fn revision(&self) -> u64;
fn topic() -> &'static str;
fn topic_com() -> &'static str;
}
pub trait Event: Archive + 'static {
type A: Aggregate;
fn apply(&self, agg: &mut Self::A);
#[inline]
fn process(&self, agg: &mut Self::A) {
self.apply(agg);
agg.next();
}
}
pub trait Command: Archive + Sized + 'static {
type A: Aggregate;
type E: Event<A = Self::A>;
fn check(&self, agg: &Self::A) -> Result<(), UniError>;
fn apply(self, agg: &Self::A) -> Self::E;
#[inline]
fn process(self, na: &mut Self::A) -> Result<Self::E, UniError> {
self.check(&na)?;
let evt = self.apply(&na);
evt.process(na);
Ok(evt)
}
}
pub trait EventEnum:
Send
+ Archive
+ Sized
+ for<'m> Serialize<Strategy<Serializer<AlignedVec, ArenaHandle<'m>, Share>, Error>>
+ 'static
where
<Self as Archive>::Archived: Deserialize<Self, Strategy<Pool, Error>>,
{
type A: Aggregate;
#[inline(always)]
fn to_bytes(&self, arena: &mut Arena) -> Result<AlignedVec, UniError> {
Ok(to_bytes_with_alloc(self, arena.acquire())?)
}
#[inline(always)]
fn from_bytes(bytes: &[u8]) -> Result<Self, UniError> {
let mut aligned = AlignedVec::<4096>::new();
aligned.extend_from_slice(bytes);
Ok(unsafe { rkyv::from_bytes_unchecked::<Self, Error>(&aligned) }?)
}
}
pub trait CommandEnum:
Send
+ Archive
+ Sized
+ Sync
+ for<'m> Serialize<Strategy<Serializer<AlignedVec, ArenaHandle<'m>, Share>, Error>>
+ 'static
where
<Self as Archive>::Archived: Deserialize<Self, Strategy<Pool, Error>>,
<<Self as CommandEnum>::E as Archive>::Archived:
Deserialize<<Self as CommandEnum>::E, Strategy<Pool, Error>>,
{
type A: Aggregate;
type E: EventEnum<A = Self::A>;
fn apply(
self,
agg_type: &'static str,
agg_id: Uuid,
agg: Self::A,
coms: &mut AHashSet<Uuid>,
loader: impl Load<Self::E>,
) -> impl Future<Output = Result<(Self::A, Self::E), UniError>> + Send;
#[inline(always)]
fn to_bytes(&self, arena: &mut Arena) -> Result<AlignedVec, UniError> {
Ok(to_bytes_with_alloc(self, arena.acquire())?)
}
#[inline(always)]
fn from_bytes(bytes: &[u8]) -> Result<Self, UniError> {
let mut aligned = AlignedVec::<4096>::new();
aligned.extend_from_slice(bytes);
Ok(unsafe { rkyv::from_bytes_unchecked::<Self, Error>(&aligned) }?)
}
}
pub trait Load<E>: Send + Copy + 'static
where
E: EventEnum,
<E as Archive>::Archived: Deserialize<E, Strategy<Pool, Error>>,
{
type Fut: Future<Output = Result<Vec<(Uuid, E)>, UniError>> + Send;
fn load(&self, agg_type: &'static str, agg_id: Uuid) -> Self::Fut;
}
pub trait Config: Sized + 'static {
fn get() -> Self;
fn reload();
}