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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//! Aggregates produce events based on commands
//!
//! An `Aggregate` is a simple Rust struct which will hold the state of the `Aggregate`.
//! The `Default` trait is mandatory because of the way the `Aggregate` works.
//!
//! An `Aggregate` is a simple struct and a bunch of functions that react to events or commands
//! to alter the state. The state of an aggregate must remain private and accessible only
//! by the aggregate itself. (Not even his parent). This prevent coupling between aggregates
//! which is a bad practice.
//!
//! An `Aggregate` must have a **unique** identity accros all `Aggregate` to perform well. See [`identity`](trait.Aggregate.html#tymethod.identity).
//!
//! An `Aggregate` will start with a blank state (this is why it needs `Default`). It will then use
//! `EventApplier` to receive and apply domain events on his state. You don't need to worry about
//! event number, stream and all the complexity of the event management, all of it are handle by
//! the parent process which is automatically generated. You just have to decide whether you apply
//! the event to the state or not. An `Aggregate` can't apply multiple event at a time meaning that
//! their is no concurrency state alteration.
//!
//! An `Aggregate` will also be the root producer of all events. `Aggregates` generate events based on
//! [`Command`](../trait.Command.html) which are pushed to him. An `Aggregate` can't execute multiple commands at a time.
//!
//! # Examples
//!
//! ```rust
//! # use chekov::prelude::*;
//! # use serde::{Deserialize, Serialize};
//! # use uuid::Uuid;
//! # use actix::Message;
//! #
//! # #[derive(Debug, Serialize)]
//! # pub enum AccountStatus {
//! # Initialized,
//! # Active,
//! # Deleted,
//! # }
//! # impl std::default::Default for AccountStatus {
//! # fn default() -> Self {
//! # Self::Initialized
//! # }
//! # }
//! #
//! # #[derive(Default)]
//! # struct DefaultApp {}
//! #
//! # impl chekov::Application for DefaultApp {
//! # type Storage = PostgresBackend;
//! # }
//! #
//! # #[derive(Clone, Message, Debug, chekov::Event, Deserialize, Serialize)]
//! # #[rtype(result = "Result<(), ()>")]
//! # pub struct AccountOpened {
//! # pub account_id: Uuid,
//! # pub name: String,
//! # }
//! #
//! # #[derive(Clone, Debug, chekov::Command, Serialize, Deserialize)]
//! # #[command(event = "AccountOpened", aggregate = "Account")]
//! # pub struct OpenAccount {
//! # #[command(identifier)]
//! # pub account_id: Uuid,
//! # pub name: String,
//! # }
//! #
//! #[derive(Debug, Default, Aggregate)]
//! #[aggregate(identity = "account")]
//! pub struct Account {
//! account_id: Option<uuid::Uuid>,
//! name: String,
//! status: AccountStatus
//! }
//!
//! // Executing commands
//! impl CommandExecutor<OpenAccount> for Account {
//! fn execute(
//! cmd: OpenAccount,
//! state: &Self
//! ) -> Result<Vec<AccountOpened>, CommandExecutorError> {
//! match state.status {
//! AccountStatus::Initialized => Ok(vec![AccountOpened {
//! account_id: cmd.account_id,
//! name: cmd.name,
//! }]),
//! _ => Err(CommandExecutorError::Any),
//! }
//! }
//! }
//!
//!
//! #[chekov::applier]
//! impl EventApplier<AccountOpened> for Account {
//! fn apply(&mut self, event: &AccountOpened) -> Result<(), ApplyError> {
//! self.account_id = Some(event.account_id);
//! self.status = AccountStatus::Active;
//!
//! Ok(())
//! }
//! }
//! ```
use crateResolveAndApplyMany;
use crate::;
use AsyncContext;
use SystemService;
use RecordedEvent;
pub use AggregateInstance;
pub use AggregateInstanceRegistry;
/// Define an Aggregate
///
/// We don't recommend implementing this trait directly. use the `Aggregate` derive macro instead
///
///
/// ```rust
/// # use chekov::prelude::*;
///
/// #[derive(Debug, Default, Aggregate)]
/// #[aggregate(identity = "account")]
/// struct Account {
/// account_id: Option<uuid::Uuid>
/// }
/// ```
///