Crate sourcerer

Source
Expand description

§Event Sourcing Framework

sourcerer is a Rust framework for building event-sourced applications. It provides the core traits and components to get started with event sourcing, including aggregates, events, event stores, and repositories.

§Core Concepts

  • Aggregate: A consistency boundary that processes commands and produces events.
  • Event: An immutable fact that represents a change in the state of an aggregate.
  • EventStore: A persistent store for events.
  • SnapshotStore: A persistent store for aggregate snapshots, used to optimize loading.
  • Repository: A high-level API for loading aggregates, handling commands, and saving events.

§Example

// 1. Define your aggregate, events, and commands.
use sourcerer::{Aggregate, AggregateId, Event, Snapshot};
use serde::{Deserialize, Serialize};
use uuid::Uuid;

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum BankAccountEvent {
    Opened { initial_balance: u64 },
    Credited { amount: u64 },
    Debited { amount: u64 },
}
impl Event for BankAccountEvent {
   fn event_type(&self) -> &'static str {
       match self {
           BankAccountEvent::Opened { .. } => "Opened",
           BankAccountEvent::Credited { .. } => "Credited",
           BankAccountEvent::Debited { .. } => "Debited",
       }
   }
   fn event_version(&self) -> u16 {
       1
   }
   fn event_source(&self) -> &'static str { "urn:sourcerer:bank" }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BankAccountSnapshot {
    balance: u64,
}
impl Snapshot for BankAccountSnapshot {}

#[derive(Debug)]
pub enum BankAccountCommand {
    Open { initial_balance: u64 },
    Deposit { amount: u64 },
    Withdraw { amount: u64 },
}

#[derive(Debug, Default)]
pub struct BankAccount {
    id: Uuid,
    balance: u64,
    version: i64,
}

// 2. Implement the Aggregate trait.
#[sourcerer::async_trait]
impl Aggregate for BankAccount {
    type Id = Uuid;
    type Event = BankAccountEvent;
    type Command = BankAccountCommand;
    type Snapshot = BankAccountSnapshot;
    type Error = std::convert::Infallible;

    fn id(&self) -> &Self::Id {
        &self.id
    }

    fn version(&self) -> i64 {
        self.version
    }

    fn apply(&mut self, event: &Self::Event) {
        match event {
            BankAccountEvent::Opened { initial_balance } => {
                self.balance = *initial_balance;
                self.id = Uuid::new_v4();
            }
            BankAccountEvent::Credited { amount } => {
                self.balance += *amount;
            }
            BankAccountEvent::Debited { amount } => {
                self.balance -= *amount;
            }
        }
        self.version += 1;
    }

    async fn handle(&self, command: Self::Command) -> Result<Vec<Self::Event>, Self::Error> {
        // Business logic and validation here...
        Ok(vec![])
    }

    fn from_snapshot(snapshot: Self::Snapshot) -> Self {
        Self {
            balance: snapshot.balance,
            ..Default::default()
        }
    }

    fn snapshot(&self) -> Self::Snapshot {
        BankAccountSnapshot {
            balance: self.balance
        }
    }
}

// 3. Use the repository to interact with your aggregate.
use sourcerer::store::in_memory::InMemoryEventStore;
use sourcerer::store::in_memory_snapshot::InMemorySnapshotStore;
use sourcerer::repository::GenericRepository;
use std::sync::Arc;

async fn bank_account_example() {
    let event_store = Arc::new(InMemoryEventStore::<BankAccount>::default());
    let snapshot_store = Arc::new(InMemorySnapshotStore::<BankAccount>::default());
    let repo = GenericRepository::new(event_store, Some(snapshot_store));

    // ...
}

Re-exports§

pub use repository::Repository;
pub use snapshot::SnapshotStore;
pub use cloudevent::CloudEvent;

Modules§

cloudevent
CloudEvent conversion utilities.
repository
Provides a generic repository for interacting with aggregates.
snapshot
The snapshot module contains the traits and structs for creating and storing aggregate snapshots.
store
The store module contains the implementations of the event and snapshot stores.
upcaster
Defines the upcasting mechanism for handling event schema versioning.

Structs§

StoredEvent
Represents a stored event, including metadata.

Enums§

Error
The error type for this crate.

Traits§

Aggregate
An aggregate is a consistency boundary. It is the fundamental building block of the domain model.
AggregateId
Uniquely identifies an aggregate instance.
Event
A marker trait for events.
EventStore
The trait for event stores.
Snapshot
A marker trait for snapshots.

Type Aliases§

Result
A specialized Result type for this crate’s operations.

Attribute Macros§

async_trait