pub struct InMemoryRepository<T: Aggregate>where
T::AggregateId: Hash + Eq,
<<T as Aggregate>::DomainEvent as DomainEvent>::EventId: Hash + Eq,
T::SideEffect: Debug + Clone,{ /* private fields */ }Expand description
An in-memory repository implementation that stores events and snapshots in memory.
This repository is useful for testing, development, and scenarios where persistent storage is not required. All data is lost when the repository is dropped.
§Example
use eventastic::memory::InMemoryRepository;
use eventastic::aggregate::{Aggregate, Root, SideEffect};
use eventastic::event::DomainEvent;
// Define a simple aggregate for demonstration
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
struct Counter {
id: String,
count: i32,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
enum CounterEvent {
Created { event_id: String, initial_count: i32 },
Incremented { event_id: String, amount: i32 },
}
impl DomainEvent for CounterEvent {
type EventId = String;
fn id(&self) -> &Self::EventId {
match self {
CounterEvent::Created { event_id, .. } => event_id,
CounterEvent::Incremented { event_id, .. } => event_id,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
struct CounterSideEffect {
id: String,
message: String,
}
impl SideEffect for CounterSideEffect {
type SideEffectId = String;
fn id(&self) -> &Self::SideEffectId {
&self.id
}
}
impl Aggregate for Counter {
const SNAPSHOT_VERSION: u64 = 1;
type AggregateId = String;
type DomainEvent = CounterEvent;
type ApplyError = String;
type SideEffect = CounterSideEffect;
fn aggregate_id(&self) -> &Self::AggregateId {
&self.id
}
fn apply_new(event: &Self::DomainEvent) -> Result<Self, Self::ApplyError> {
match event {
CounterEvent::Created { initial_count, .. } => Ok(Counter {
id: "counter-1".to_string(),
count: *initial_count,
}),
_ => Err("Counter must start with Created event".to_string()),
}
}
fn apply(&mut self, event: &Self::DomainEvent) -> Result<(), Self::ApplyError> {
match event {
CounterEvent::Created { .. } => Err("Counter already exists".to_string()),
CounterEvent::Incremented { amount, .. } => {
self.count += amount;
Ok(())
}
}
}
fn side_effects(&self, _event: &Self::DomainEvent) -> Option<Vec<Self::SideEffect>> {
None
}
}
// Create a repository for your aggregate type
use eventastic::repository::Repository;
let repository: InMemoryRepository<Counter> = InMemoryRepository::new();
// Use transactions to store aggregates
let mut aggregate = Counter::record_new(CounterEvent::Created {
event_id: "event-1".to_string(),
initial_count: 0,
})?;
let mut transaction = repository.begin_transaction().await?;
transaction.store(&mut aggregate).await?;
transaction.commit()?;
// Load aggregates using the Repository trait
let loaded = repository.load(&"counter-1".to_string()).await?;
assert_eq!(loaded.state().count, 0);Implementations§
Source§impl<T: Aggregate> InMemoryRepository<T>where
T::AggregateId: Hash + Eq,
<<T as Aggregate>::DomainEvent as DomainEvent>::EventId: Hash + Eq,
T::SideEffect: Debug + Clone,
impl<T: Aggregate> InMemoryRepository<T>where
T::AggregateId: Hash + Eq,
<<T as Aggregate>::DomainEvent as DomainEvent>::EventId: Hash + Eq,
T::SideEffect: Debug + Clone,
Sourcepub fn get_event(
&self,
aggregate_id: &T::AggregateId,
event_id: &<<T as Aggregate>::DomainEvent as DomainEvent>::EventId,
) -> Option<EventStoreEvent<T::DomainEvent>>
pub fn get_event( &self, aggregate_id: &T::AggregateId, event_id: &<<T as Aggregate>::DomainEvent as DomainEvent>::EventId, ) -> Option<EventStoreEvent<T::DomainEvent>>
Gets a specific event by ID.
Sourcepub fn get_events_from(
&self,
aggregate_id: &T::AggregateId,
from_version: u64,
) -> Vec<EventStoreEvent<T::DomainEvent>>
pub fn get_events_from( &self, aggregate_id: &T::AggregateId, from_version: u64, ) -> Vec<EventStoreEvent<T::DomainEvent>>
Gets all events for an aggregate starting from a specific version.
Sourcepub fn side_effects_count(&self) -> usize
pub fn side_effects_count(&self) -> usize
Returns the number of stored side effects.
Sourcepub fn get_all_side_effects(&self) -> Vec<T::SideEffect>
pub fn get_all_side_effects(&self) -> Vec<T::SideEffect>
Returns all stored side effects.
Source§impl<T> InMemoryRepository<T>where
T::AggregateId: Hash + Eq + Send + Sync,
<<T as Aggregate>::DomainEvent as DomainEvent>::EventId: Hash + Eq + Send + Sync,
T::SideEffect: Debug + Clone + Send + Sync,
T: Send + Sync + Aggregate,
T::DomainEvent: Send + Sync,
T::ApplyError: Send + Sync,
impl<T> InMemoryRepository<T>where
T::AggregateId: Hash + Eq + Send + Sync,
<<T as Aggregate>::DomainEvent as DomainEvent>::EventId: Hash + Eq + Send + Sync,
T::SideEffect: Debug + Clone + Send + Sync,
T: Send + Sync + Aggregate,
T::DomainEvent: Send + Sync,
T::ApplyError: Send + Sync,
Sourcepub async fn begin_transaction(
&self,
) -> Result<InMemoryTransaction<T>, InMemoryError>
pub async fn begin_transaction( &self, ) -> Result<InMemoryTransaction<T>, InMemoryError>
Begins a new “transaction” (returns a transaction-like wrapper).
Trait Implementations§
Source§impl<T: Clone + Aggregate> Clone for InMemoryRepository<T>where
T::AggregateId: Hash + Eq,
<<T as Aggregate>::DomainEvent as DomainEvent>::EventId: Hash + Eq,
T::SideEffect: Debug + Clone,
impl<T: Clone + Aggregate> Clone for InMemoryRepository<T>where
T::AggregateId: Hash + Eq,
<<T as Aggregate>::DomainEvent as DomainEvent>::EventId: Hash + Eq,
T::SideEffect: Debug + Clone,
Source§fn clone(&self) -> InMemoryRepository<T>
fn clone(&self) -> InMemoryRepository<T>
Returns a duplicate of the value. Read more
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreSource§impl<T: Debug + Aggregate> Debug for InMemoryRepository<T>where
T::AggregateId: Hash + Eq,
<<T as Aggregate>::DomainEvent as DomainEvent>::EventId: Hash + Eq,
T::SideEffect: Debug + Clone,
impl<T: Debug + Aggregate> Debug for InMemoryRepository<T>where
T::AggregateId: Hash + Eq,
<<T as Aggregate>::DomainEvent as DomainEvent>::EventId: Hash + Eq,
T::SideEffect: Debug + Clone,
Source§impl<T: Aggregate> Default for InMemoryRepository<T>where
T::AggregateId: Hash + Eq,
<<T as Aggregate>::DomainEvent as DomainEvent>::EventId: Hash + Eq,
T::SideEffect: Debug + Clone,
impl<T: Aggregate> Default for InMemoryRepository<T>where
T::AggregateId: Hash + Eq,
<<T as Aggregate>::DomainEvent as DomainEvent>::EventId: Hash + Eq,
T::SideEffect: Debug + Clone,
Source§impl<T> Repository<T> for InMemoryRepository<T>where
T::AggregateId: Hash + Eq + Send + Sync,
<<T as Aggregate>::DomainEvent as DomainEvent>::EventId: Hash + Eq + Send + Sync,
T::SideEffect: Debug + Clone + Send + Sync,
T: Send + Sync + Aggregate,
T::DomainEvent: Send + Sync,
T::ApplyError: Send + Sync,
impl<T> Repository<T> for InMemoryRepository<T>where
T::AggregateId: Hash + Eq + Send + Sync,
<<T as Aggregate>::DomainEvent as DomainEvent>::EventId: Hash + Eq + Send + Sync,
T::SideEffect: Debug + Clone + Send + Sync,
T: Send + Sync + Aggregate,
T::DomainEvent: Send + Sync,
T::ApplyError: Send + Sync,
Source§type Error = InMemoryError
type Error = InMemoryError
The error type returned by the Repository during operations.
Source§fn load<'life0, 'life1, 'async_trait>(
&'life0 self,
aggregate_id: &'life1 T::AggregateId,
) -> Pin<Box<dyn Future<Output = Result<Context<T>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn load<'life0, 'life1, 'async_trait>(
&'life0 self,
aggregate_id: &'life1 T::AggregateId,
) -> Pin<Box<dyn Future<Output = Result<Context<T>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Loads an aggregate from the repository by its ID. Read more
Auto Trait Implementations§
impl<T> Freeze for InMemoryRepository<T>
impl<T> RefUnwindSafe for InMemoryRepository<T>
impl<T> Send for InMemoryRepository<T>where
<T as Aggregate>::SideEffect: Sized + Send,
<T as Aggregate>::AggregateId: Send,
<<T as Aggregate>::DomainEvent as DomainEvent>::EventId: Send,
T: Send,
<T as Aggregate>::DomainEvent: Send,
impl<T> Sync for InMemoryRepository<T>where
<T as Aggregate>::SideEffect: Sized + Send,
<T as Aggregate>::AggregateId: Send,
<<T as Aggregate>::DomainEvent as DomainEvent>::EventId: Send,
T: Send,
<T as Aggregate>::DomainEvent: Send,
impl<T> Unpin for InMemoryRepository<T>
impl<T> UnwindSafe for InMemoryRepository<T>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more