armature_eventsourcing/lib.rs
1//! Event Sourcing for Armature
2//!
3//! This crate provides event sourcing capabilities with aggregates and event stores.
4//!
5//! ## Features
6//!
7//! - **Aggregates** - Event-sourced aggregate roots
8//! - **Event Store** - Persistent event storage
9//! - **Snapshots** - Aggregate snapshots for performance
10//! - **Repository** - Load/save aggregates
11//! - **Optimistic Concurrency** - Version-based conflict detection
12//!
13//! ## Quick Start
14//!
15//! ```rust,ignore
16//! use armature_eventsourcing::*;
17//! use armature_events::DomainEvent;
18//! use async_trait::async_trait;
19//! use serde::{Deserialize, Serialize};
20//!
21//! // Define aggregate state
22//! #[derive(Debug, Clone, Serialize, Deserialize)]
23//! struct UserState {
24//! email: String,
25//! active: bool,
26//! }
27//!
28//! // Define aggregate
29//! #[derive(Debug, Clone, Serialize, Deserialize)]
30//! struct UserAggregate {
31//! #[serde(flatten)]
32//! root: AggregateRoot<UserState>,
33//! }
34//!
35//! #[async_trait]
36//! impl Aggregate for UserAggregate {
37//! fn aggregate_id(&self) -> &str { &self.root.id }
38//! fn aggregate_type() -> &'static str { "User" }
39//! fn version(&self) -> u64 { self.root.version }
40//!
41//! fn apply_event(&mut self, event: &DomainEvent) -> Result<(), AggregateError> {
42//! match event.metadata.name.as_str() {
43//! "user_created" => {
44//! self.root.state.email = event.payload["email"].as_str().unwrap().to_string();
45//! self.root.state.active = true;
46//! self.root.increment_version();
47//! }
48//! "user_deactivated" => {
49//! self.root.state.active = false;
50//! self.root.increment_version();
51//! }
52//! _ => {}
53//! }
54//! Ok(())
55//! }
56//!
57//! fn uncommitted_events(&self) -> &[DomainEvent] { &self.root.uncommitted_events }
58//! fn mark_events_committed(&mut self) { self.root.uncommitted_events.clear(); }
59//!
60//! fn new_instance(id: String) -> Self {
61//! Self {
62//! root: AggregateRoot::new(id, UserState {
63//! email: String::new(),
64//! active: false,
65//! }),
66//! }
67//! }
68//! }
69//!
70//! // Use the repository
71//! #[tokio::main]
72//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
73//! // Create event store
74//! let store = Arc::new(InMemoryEventStore::new());
75//!
76//! // Create repository
77//! let repo = AggregateRepository::<UserAggregate, _>::new(store);
78//!
79//! // Create new aggregate
80//! let mut user = UserAggregate::new_instance("user-123".to_string());
81//!
82//! // Add event
83//! user.root.add_event(DomainEvent::new(
84//! "user_created",
85//! "user-123",
86//! "User",
87//! serde_json::json!({"email": "alice@example.com"}),
88//! ));
89//!
90//! // Apply event
91//! let event = user.root.uncommitted_events[0].clone();
92//! user.apply_event(&event)?;
93//!
94//! // Save aggregate
95//! repo.save(&mut user).await?;
96//!
97//! // Load aggregate
98//! let loaded = repo.load("user-123").await?;
99//! println!("Loaded user: {:?}", loaded);
100//!
101//! Ok(())
102//! }
103//! ```
104//!
105//! ## Snapshots
106//!
107//! ```rust,ignore
108//! // Enable snapshots every 10 events
109//! let repo = AggregateRepository::<UserAggregate, _>::with_snapshots(store, 10);
110//! ```
111
112pub mod aggregate;
113pub mod repository;
114pub mod store;
115
116pub use aggregate::{Aggregate, AggregateError, AggregateRoot, Snapshot};
117pub use repository::AggregateRepository;
118pub use store::{EventStore, EventStoreError, InMemoryEventStore};
119
120#[cfg(test)]
121mod tests {
122 #[test]
123 fn test_module_exports() {
124 // Ensure module compiles
125 }
126}