armature_cqrs/
lib.rs

1//! CQRS (Command Query Responsibility Segregation) for Armature
2//!
3//! This crate provides CQRS pattern implementation with command/query separation.
4//!
5//! ## Features
6//!
7//! - **Command Bus** - Execute commands (writes)
8//! - **Query Bus** - Execute queries (reads)
9//! - **Projections** - Build read models from events
10//! - **Type-safe** - Strong typing with compile-time safety
11//! - **Async** - Full async/await support
12//!
13//! ## Quick Start
14//!
15//! ```rust,ignore
16//! use armature_cqrs::*;
17//! use async_trait::async_trait;
18//!
19//! // Define a command
20//! struct CreateUserCommand {
21//!     email: String,
22//! }
23//!
24//! impl Command for CreateUserCommand {
25//!     type Result = String; // User ID
26//! }
27//!
28//! // Define command handler
29//! struct CreateUserHandler;
30//!
31//! #[async_trait]
32//! impl CommandHandler<CreateUserCommand> for CreateUserHandler {
33//!     async fn handle(&self, command: CreateUserCommand) -> Result<String, CommandError> {
34//!         // Business logic here
35//!         Ok(format!("user-{}", uuid::Uuid::new_v4()))
36//!     }
37//! }
38//!
39//! // Define a query
40//! struct GetUserQuery {
41//!     user_id: String,
42//! }
43//!
44//! impl Query for GetUserQuery {
45//!     type Result = User;
46//! }
47//!
48//! // Define query handler
49//! struct GetUserHandler;
50//!
51//! #[async_trait]
52//! impl QueryHandler<GetUserQuery> for GetUserHandler {
53//!     async fn handle(&self, query: GetUserQuery) -> Result<User, QueryError> {
54//!         // Fetch from read model
55//!         Ok(User {
56//!             id: query.user_id,
57//!             email: "alice@example.com".to_string(),
58//!         })
59//!     }
60//! }
61//!
62//! // Use the buses
63//! #[tokio::main]
64//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
65//!     // Create buses
66//!     let command_bus = CommandBus::new();
67//!     let query_bus = QueryBus::new();
68//!
69//!     // Register handlers
70//!     command_bus.register::<CreateUserCommand, _>(CreateUserHandler);
71//!     query_bus.register::<GetUserQuery, _>(GetUserHandler);
72//!
73//!     // Execute command
74//!     let user_id = command_bus.execute(CreateUserCommand {
75//!         email: "alice@example.com".to_string(),
76//!     }).await?;
77//!
78//!     // Execute query
79//!     let user = query_bus.execute(GetUserQuery { user_id }).await?;
80//!     println!("User: {:?}", user);
81//!
82//!     Ok(())
83//! }
84//! ```
85//!
86//! ## Projections
87//!
88//! ```rust,ignore
89//! use armature_events::Event;
90//! use async_trait::async_trait;
91//!
92//! struct UserListProjection {
93//!     // Read model storage
94//! }
95//!
96//! #[async_trait]
97//! impl Projection for UserListProjection {
98//!     async fn project(&self, event: &dyn Event) -> Result<(), ProjectionError> {
99//!         match event.event_name() {
100//!             "user_created" => {
101//!                 // Update read model
102//!             }
103//!             "user_deleted" => {
104//!                 // Update read model
105//!             }
106//!             _ => {}
107//!         }
108//!         Ok(())
109//!     }
110//! }
111//! ```
112//!
113//! ## Integration with Event Sourcing
114//!
115//! ```rust,ignore
116//! use armature_eventsourcing::*;
117//! use armature_events::EventBus;
118//!
119//! // Command handler uses aggregate repository
120//! #[async_trait]
121//! impl CommandHandler<CreateUserCommand> for CreateUserHandler {
122//!     async fn handle(&self, command: CreateUserCommand) -> Result<String, CommandError> {
123//!         let mut user = UserAggregate::new_instance(uuid::Uuid::new_v4().to_string());
124//!
125//!         // Add domain event
126//!         user.create(command.email)?;
127//!
128//!         // Save aggregate (persists events)
129//!         self.repository.save(&mut user).await?;
130//!
131//!         // Publish events to event bus for projections
132//!         for event in user.uncommitted_events() {
133//!             self.event_bus.publish(event.clone()).await?;
134//!         }
135//!
136//!         Ok(user.aggregate_id().to_string())
137//!     }
138//! }
139//! ```
140
141pub mod command;
142pub mod projection;
143pub mod query;
144
145pub use command::{Command, CommandBus, CommandError, CommandHandler};
146pub use projection::{Projection, ProjectionError, ProjectionEventHandler, ProjectionManager};
147pub use query::{Query, QueryBus, QueryError, QueryHandler};
148
149#[cfg(test)]
150mod tests {
151    #[test]
152    fn test_module_exports() {
153        // Ensure module compiles
154    }
155}