evento 1.2.0

A collection of libraries and tools that help you build DDD, CQRS, and event sourcing.
Documentation

Evento - Event Sourcing and CQRS Framework

Evento is a comprehensive library for building event-sourced applications using Domain-Driven Design (DDD) and Command Query Responsibility Segregation (CQRS) patterns in Rust.

Overview

Event sourcing is a pattern where state changes are stored as a sequence of events. Instead of persisting just the current state, you persist all the events that led to the current state. This provides:

  • Complete audit trail: Every change is recorded as an event
  • Time travel: Replay events to see state at any point in time
  • Event-driven architecture: React to events with handlers
  • CQRS support: Separate read and write models

Core Concepts

  • Events: Immutable facts representing something that happened
  • Aggregates: Domain objects that process events and maintain state
  • Event Handlers: Functions that react to events and trigger side effects
  • Event Store: Persistent storage for events (SQL databases supported)
  • Snapshots: Periodic state captures to optimize loading

Quick Start

use evento::prelude::*;
use evento::{EventDetails, AggregatorName};
use serde::{Deserialize, Serialize};
use bincode::{Decode, Encode};

// Define events
#[derive(AggregatorName, Encode, Decode)]
struct UserCreated {
    name: String,
    email: String,
}

// Define aggregate
#[derive(Default, Serialize, Deserialize, Encode, Decode, Clone, Debug)]
struct User {
    name: String,
    email: String,
}

// Implement event handlers on the aggregate
#[evento::aggregator]
impl User {
    async fn user_created(&mut self, event: EventDetails<UserCreated>) -> anyhow::Result<()> {
        self.name = event.data.name;
        self.email = event.data.email;
        Ok(())
    }
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Setup SQLite executor
    let pool = sqlx::SqlitePool::connect("sqlite:events.db").await?;
    let executor: evento::Sqlite = pool.into();

    // Create and save events
    let user_id = evento::create::<User>()
        .data(&UserCreated {
            name: "John Doe".to_string(),
            email: "john@example.com".to_string(),
        })?
        .metadata(&true)?
        .commit(&executor)
        .await?;

    // Load aggregate from events
    let user = evento::load::<User, _>(&executor, &user_id).await?;
    println!("User: {:?}", user.item);

    Ok(())
}

Features

  • SQL Database Support: SQLite, PostgreSQL, MySQL
  • Event Handlers: Async event processing with retries
  • Event Subscriptions: Continuous event processing
  • Streaming: Real-time event streams (with stream feature)
  • Migrations: Database schema management
  • Macros: Procedural macros for cleaner code

Feature Flags

  • macro - Enable procedural macros (default)
  • handler - Enable event handlers (default)
  • stream - Enable streaming support
  • sql - Enable all SQL database backends
  • sqlite - SQLite support
  • postgres - PostgreSQL support
  • mysql - MySQL support
  • sql-migrator - Enable database migrations