1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
use serde::{ de::DeserializeOwned, Serialize, }; use crate::events::DomainEvent; use super::errors::AggregateError; /// In CQRS (and Domain Driven Design) an `Aggregate` is the /// fundamental component that encapsulates the state and application /// logic (aka business rules) for the application. An `Aggregate` is /// always an entity along with all objects associated with it. /// /// # Examples /// ```rust /// # use cqrs_es2::doc::{CustomerEvent, CustomerCommand, NameAdded}; /// # use cqrs_es2::{Aggregate, AggregateError}; /// # use serde::{Serialize,Deserialize}; /// #[derive(Serialize,Deserialize)] /// struct Customer { /// customer_id: String, /// name: String, /// email: String, /// } /// /// impl Aggregate for Customer { /// type Command = CustomerCommand; /// type Event = CustomerEvent; /// /// fn aggregate_type() -> &'static str { "customer" } /// /// fn handle(&self, command: Self::Command) -> Result<Vec<Self::Event>, AggregateError> { /// match command { /// CustomerCommand::AddCustomerName(payload) => { /// if self.name.as_str() != "" { /// return Err(AggregateError::new("a name has already been added for this customer")); /// } /// let payload = NameAdded { /// changed_name: payload.changed_name /// }; /// Ok(vec![CustomerEvent::NameAdded(payload)]) /// } /// CustomerCommand::UpdateEmail(_) => { /// Ok(Default::default()) /// } /// } /// } /// /// fn apply(&mut self, event: &Self::Event) { /// match event { /// CustomerEvent::NameAdded(payload) => { /// self.name = payload.changed_name.clone(); /// } /// CustomerEvent::EmailUpdated(payload) => { /// self.email = payload.new_email.clone(); /// } /// } /// } /// } /// /// impl Default for Customer {fn default() -> Self { /// Customer { /// customer_id: "".to_string(), /// name: "".to_string(), /// email: "".to_string(), /// } /// } /// } /// ``` pub trait Aggregate: Default + Serialize + DeserializeOwned + Sync + Send { /// An inbound command used to make changes in the state of the /// Aggregate type Command; /// An event representing some change in state of the Aggregate type Event: DomainEvent; /// aggregate_type is a unique identifier for this aggregate fn aggregate_type() -> &'static str; /// handle inbound command and return a vector of events or an /// error fn handle( &self, command: Self::Command, ) -> Result<Vec<Self::Event>, AggregateError>; /// Update the aggregate's state with an event fn apply( &mut self, event: &Self::Event, ); }