Skip to main content

Crate sourcery

Crate sourcery 

Source
Expand description

§sourcery

Continuous integration codecov

Building blocks for pragmatic event-sourced systems in Rust.

§Highlights

  • Domain-first API – events are plain structs that implement DomainEvent; IDs and metadata live in an envelope rather than in your payloads.
  • Aggregate derive#[derive(Aggregate)] generates the event enum plus serialisation/deserialisation glue so command handlers stay focused on behaviour.
  • Repository orchestrationRepository loads aggregates, executes commands via Handle<C>, and persists the resulting events in a single transaction.
  • Metadata-aware projections – projections receive aggregate IDs, events, and metadata via ApplyProjection, enabling cross-aggregate correlation using causation, timestamps, or custom metadata.
  • Store agnostic – ships with an in-memory store for demos/tests; implement the EventStore trait to plug in your own persistence.

§Quick Look

use sourcery::{Apply, DomainEvent, Handle};
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct FundsDeposited { pub amount_cents: i64 }

impl DomainEvent for FundsDeposited {
    const KIND: &'static str = "bank.account.deposited";
}

#[derive(Debug, Default, sourcery::Aggregate)]
#[aggregate(id = String, error = String, events(FundsDeposited))]
pub struct Account { balance_cents: i64 }

impl Apply<FundsDeposited> for Account {
    fn apply(&mut self, event: &FundsDeposited) {
        self.balance_cents += event.amount_cents;
    }
}

pub struct DepositFunds { pub amount_cents: i64 }

impl Handle<DepositFunds> for Account {
    fn handle(&self, cmd: &DepositFunds) -> Result<Vec<Self::Event>, Self::Error> {
        Ok(vec![FundsDeposited { amount_cents: cmd.amount_cents }.into()])
    }
}

§Key Concepts

ConceptDescription
AggregatesRebuild state from events and validate commands via Apply<E> and Handle<C>.
ProjectionsRead models that replay events via ApplyProjection<E>, potentially across multiple aggregates.
RepositoryOrchestrates loading, command execution, and persistence in a single transaction.
EventStoreTrait defining the persistence boundary—implement for Postgres, DynamoDB, S3, etc.

§Documentation

§Examples

ExampleDescription
quickstartMinimal aggregate + projection
inventory_reportCross-aggregate projection
subscription_billingReal-world billing domain
versioned_eventsSchema migration via serde
optimistic_concurrencyConflict detection and retry
snapshottingAggregate snapshots for performance
cargo run --example quickstart

§Status

Pre-1.0. APIs will evolve as real-world usage grows. Feedback and contributions welcome!

§Licensing

This project is publicly available under the GNU General Public License v3.0. It may optionally be distributed under the MIT licence by commercial arrangement.


Was this useful? Buy me a coffee

Modules§

aggregate
Command-side domain primitives.
event
Domain event marker.
projection
Read-side primitives.
repository
Command execution and aggregate lifecycle management.
snapshot
store
subscription
Push-based projection subscriptions.

Structs§

Filters
Combined filter configuration and handler map for a subscriber.
Repository
Command execution and aggregate lifecycle orchestrator.
SubscriptionBuilder
Builder for configuring and starting a subscription.
SubscriptionHandle
Handle to a running subscription.

Enums§

EventDecodeError
Error returned when deserialising a stored event fails.
SubscriptionError
Errors that can occur during subscription lifecycle.

Traits§

Aggregate
Command-side entities that produce domain events.
Apply
Mutate an aggregate with a domain event.
ApplyProjection
Apply an event to a projection with access to envelope context.
DomainEvent
Marker trait for events that can be persisted by the event store.
EventKind
Extension trait for getting the event kind from an event instance.
Handle
Entry point for command handling.
Projection
Trait implemented by read models that can be constructed from an event stream.
ProjectionEvent
Trait for event sum types that can deserialise themselves from stored events.
ProjectionFilters
Base trait for types that subscribe to events.
SubscribableStore
A store that supports push-based event subscriptions.

Type Aliases§

OptimisticRepository
Repository type alias with optimistic concurrency and no snapshots.
OptimisticSnapshotRepository
Repository type alias with optimistic concurrency and snapshot support.
UncheckedRepository
Repository type alias with unchecked concurrency and no snapshots.

Derive Macros§

Aggregate
Derives the Aggregate trait for a struct.
Projection
Derives the Projection trait for a struct.