use std::borrow::Cow;
use serde::{Deserialize, Serialize};
use crate::id::Id;
use crate::time::Timestamp;
pub struct EventTag;
pub type EventId = Id<EventTag>;
pub trait DomainEvent {
fn event_type(&self) -> &'static str;
fn schema_version(&self) -> u32 {
1
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct EventEnvelope<E> {
pub event_id: EventId,
pub event_type: Cow<'static, str>,
pub aggregate_id: String,
pub aggregate_type: Cow<'static, str>,
pub sequence: u64,
pub occurred_at: Timestamp,
pub payload: E,
}
impl<E: DomainEvent> EventEnvelope<E> {
pub fn new(
aggregate_id: String,
aggregate_type: &'static str,
sequence: u64,
occurred_at: Timestamp,
payload: E,
) -> Self {
Self {
event_id: EventId::new(),
event_type: Cow::Borrowed(payload.event_type()),
aggregate_id,
aggregate_type: Cow::Borrowed(aggregate_type),
sequence,
occurred_at,
payload,
}
}
}
#[derive(Debug, Clone)]
pub struct EventLog<E> {
pending: Vec<E>,
version: u64,
}
impl<E> EventLog<E> {
pub fn new() -> Self {
Self { pending: Vec::new(), version: 0 }
}
pub fn with_version(version: u64) -> Self {
Self { pending: Vec::new(), version }
}
pub fn record(&mut self, event: E) {
self.pending.push(event);
self.version += 1;
}
pub fn take(&mut self) -> Vec<E> {
std::mem::take(&mut self.pending)
}
pub fn pending(&self) -> &[E] {
&self.pending
}
pub fn version(&self) -> u64 {
self.version
}
pub fn is_empty(&self) -> bool {
self.pending.is_empty()
}
pub fn len(&self) -> usize {
self.pending.len()
}
}
impl<E> Default for EventLog<E> {
fn default() -> Self {
Self::new()
}
}