use std::fmt;
use crate::time::Timestamp;
use super::{DomainEvent, Entity, EventEnvelope, EventLog};
pub trait AggregateRoot: Entity {
type Event: DomainEvent;
fn aggregate_type() -> &'static str;
fn event_log(&self) -> &EventLog<Self::Event>;
fn event_log_mut(&mut self) -> &mut EventLog<Self::Event>;
fn version(&self) -> u64 {
self.event_log().version()
}
fn record(&mut self, event: Self::Event) {
self.event_log_mut().record(event);
}
fn pending_events(&self) -> &[Self::Event] {
self.event_log().pending()
}
fn take_events(&mut self) -> Vec<Self::Event> {
self.event_log_mut().take()
}
fn drain_envelopes(&mut self, occurred_at: Timestamp) -> Vec<EventEnvelope<Self::Event>>
where
Self::Id: fmt::Display,
{
let aggregate_id = self.id().to_string();
let aggregate_type = Self::aggregate_type();
let events = self.take_events();
let end = self.version();
let start = end + 1 - events.len() as u64;
events
.into_iter()
.enumerate()
.map(|(offset, payload)| {
EventEnvelope::new(
aggregate_id.clone(),
aggregate_type,
start + offset as u64,
occurred_at,
payload,
)
})
.collect()
}
}
#[async_trait::async_trait]
pub trait Repository<A>: Send + Sync
where
A: AggregateRoot + Send + Sync,
A::Id: Send + Sync,
{
type Error;
async fn find(&self, id: &A::Id) -> Result<Option<A>, Self::Error>;
async fn save(&self, aggregate: &mut A) -> Result<(), Self::Error>;
async fn delete(&self, id: &A::Id) -> Result<(), Self::Error>;
}