use uuid::Uuid;
use crate::store::EventStoreLockGuard;
use crate::store::StoreEvent;
use crate::types::SequenceNumber;
pub struct AggregateState<S> {
id: Uuid,
sequence_number: SequenceNumber,
lock: Option<EventStoreLockGuard>,
inner: S,
}
impl<S: std::fmt::Debug> std::fmt::Debug for AggregateState<S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AggregateState")
.field("id", &self.id)
.field("sequence_number", &self.sequence_number)
.field("lock", &self.lock.is_some())
.field("inner", &self.inner)
.finish()
}
}
impl<S: Default> Default for AggregateState<S> {
fn default() -> Self {
Self::new()
}
}
impl<S: Default> AggregateState<S> {
pub fn new() -> Self {
Self {
id: Uuid::new_v4(),
inner: Default::default(),
sequence_number: 0,
lock: None,
}
}
pub fn with_id(id: impl Into<Uuid>) -> Self {
Self {
id: id.into(),
inner: Default::default(),
sequence_number: 0,
lock: None,
}
}
pub fn apply_store_events<T, F>(self, store_events: Vec<StoreEvent<T>>, apply_event: F) -> Self
where
F: Fn(S, T) -> S,
{
store_events.into_iter().fold(self, |state, store_event| {
let sequence_number = *store_event.sequence_number();
let inner = apply_event(state.inner, store_event.payload);
Self {
sequence_number,
inner,
..state
}
})
}
pub const fn id(&self) -> &Uuid {
&self.id
}
pub const fn inner(&self) -> &S {
&self.inner
}
pub fn into_inner(self) -> S {
self.inner
}
pub const fn sequence_number(&self) -> &SequenceNumber {
&self.sequence_number
}
pub fn next_sequence_number(&mut self) -> SequenceNumber {
self.sequence_number += 1;
self.sequence_number
}
pub fn set_lock(&mut self, guard: EventStoreLockGuard) {
self.lock = Some(guard);
}
pub fn take_lock(&mut self) -> Option<EventStoreLockGuard> {
self.lock.take()
}
}