use async_trait::async_trait;
use aws_sdk_dynamodb::types::error::TransactionCanceledException;
use chrono::{DateTime, Utc};
use serde::{de, Serialize};
use std::error::Error as StdError;
use std::fmt::{Debug, Display};
use thiserror::Error;
pub trait AggregateId:
std::fmt::Display + Debug + Clone + Serialize + for<'de> de::Deserialize<'de> + Send + Sync + 'static {
fn type_name(&self) -> String;
fn value(&self) -> String;
}
pub trait Event: Debug + Clone + Serialize + for<'de> de::Deserialize<'de> + Send + Sync + 'static {
type ID: std::fmt::Display;
type AggregateID: AggregateId;
fn id(&self) -> &Self::ID;
fn aggregate_id(&self) -> &Self::AggregateID;
fn seq_nr(&self) -> usize;
fn occurred_at(&self) -> &DateTime<Utc>;
fn is_created(&self) -> bool;
}
pub trait Aggregate: Debug + Clone + Serialize + for<'de> de::Deserialize<'de> + Send + Sync + 'static {
type ID: AggregateId;
fn id(&self) -> &Self::ID;
fn seq_nr(&self) -> usize;
fn version(&self) -> usize;
fn set_version(&mut self, version: usize);
fn last_updated_at(&self) -> &DateTime<Utc>;
}
#[async_trait]
pub trait EventStore: Debug + Clone + Sync + Send + 'static {
type EV: Event;
type AG: Aggregate;
type AID: AggregateId;
async fn persist_event(&mut self, event: &Self::EV, version: usize) -> Result<(), EventStoreWriteError>;
async fn persist_event_and_snapshot(
&mut self,
event: &Self::EV,
aggregate: &Self::AG,
) -> Result<(), EventStoreWriteError>;
async fn get_latest_snapshot_by_id(&self, aid: &Self::AID) -> Result<Option<Self::AG>, EventStoreReadError>;
async fn get_events_by_id_since_seq_nr(
&self,
aid: &Self::AID,
seq_nr: usize,
) -> Result<Vec<Self::EV>, EventStoreReadError>;
}
#[derive(Debug)]
pub struct TransactionCanceledExceptionWrapper(pub Option<TransactionCanceledException>);
impl Display for TransactionCanceledExceptionWrapper {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self.0 {
Some(e) => write!(f, "{}", e),
None => write!(f, "No TransactionCanceledException"),
}
}
}
impl StdError for TransactionCanceledExceptionWrapper {}
#[derive(Error, Debug)]
pub enum EventStoreWriteError {
#[error("SerializeError: {0}")]
SerializationError(Box<dyn StdError + Send + Sync>),
#[error("TransactionCanceledError: {0}")]
OptimisticLockError(#[from] TransactionCanceledExceptionWrapper),
#[error("IOError: {0}")]
IOError(#[from] Box<dyn StdError + Send + Sync>),
#[error("OtherError: {0}")]
OtherError(String),
}
#[derive(Error, Debug)]
pub enum EventStoreReadError {
#[error("DeserializeError: {0}")]
DeserializationError(Box<dyn StdError + Send + Sync>),
#[error("IOError: {0}")]
IOError(#[from] Box<dyn StdError + Send + Sync>),
#[error("OtherError: {0}")]
OtherError(String),
}