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 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
//! A library providing components to build event-sourced applications. //! //! The `eventually` crate provides base abstractions to design your application //! domain using [Domain-driven Design], using the [`Aggregate`] trait, //! and provides a set of nice utilities around those core abstractions: //! [`EventStore`], [`Repository`], [`Subscription`] and [`Projection`]. //! //! ## Event Sourcing Primer //! //! Event Sourcing is an architectural pattern which requires domain entities' //! (in ES lingo, **_Aggregates_**) internal state to be mutated and persisted //! as a list of **_Domain Events_**, rather than serializing the whole state //! to the database (as you would do with a typical CRUD architecture). //! //! Events are persisted in an **_Event Store_**: an ordered, append-only log of all //! the events produced in your domain. //! //! Events can be retrieved from an Event Store through **_Event Streams_**, //! stream of chronologically-ordered events. //! //! The state of your Aggregates can thus be rebuilt by **streaming all the Events** //! back in the application, as they happened in time, to build the latest version //! of the state. //! //! This architectural pattern brings in a lot of interesting goodies: //! * **Auditing**: never need to guess what happened in your system, //! thanks to the Event Store, you have a list of all the Events that have been committed //! during time. //! * **Time-machine**: _travel back in time_, by setting the state of your service //! to a specific point in time, thanks to the Event Store; useful for debugging purposes. //! * **Projections**: create read-optimized models of your Aggregates as needed //! for you business operations, continuously, every time new Events are committed //! to the Event Store. //! * **Concurrency Handling**: Event-sourced application make extensive use //! of Optimistic Concurrency to handle concurrent-writes scenarios -- concurrency //! conflicts and state reconciliation can become part of your Domain! //! * **High Performance, High Availability**: thanks to the append-only Event Store //! and the use of Projections, you can write highly performant and highly available //! services that handle an intense amount of traffic. //! //! [More information about this pattern can be found here.](https://eventstore.com/blog/what-is-event-sourcing/) //! //! [Domain-driven Design]: https://en.wikipedia.org/wiki/Domain-driven_design //! [`Aggregate`]: trait.Aggregate.html //! [`EventStore`]: trait.EventStore.html //! [`Repository`]: struct.Repository.html //! [`Subscription`]: trait.Subscription.html //! [`Projection`]: trait.Projection.html pub use eventually_core::aggregate::{ Aggregate, AggregateExt, AggregateId, AggregateRoot, AggregateRootBuilder, }; pub use eventually_core::projection::Projection; pub use eventually_core::repository::Repository; pub use eventually_core::store::EventStore; pub use eventually_core::subscription::{EventSubscriber, Subscription}; pub use eventually_core::versioning::Versioned; pub use eventually_util::inmemory::Projector; pub use eventually_util::spawn; pub mod aggregate { //! Module containing support for the Aggergate pattern. //! //! ## What is an Aggregate? //! //! An [Aggregate] is the most important concept in your domain. //! //! It represents the entities your business domain is composed of, //! and the business logic your domain is exposing. //! //! For example: in an Order Management bounded-context (e.g. a microservice), //! the concepts of Order or Customer are two potential [Aggregate]s. //! //! Aggregates expose mutations with the concept of **commands**: //! from the previous example, an Order might expose some commands such as //! _"Add Order Item"_, or _"Remove Order Item"_, or _"Place Order"_ //! to close the transaction. //! //! In Event Sourcing, the Aggregate state is modified by the usage of //! **Domain Events**, which carry some or all the fields in the state //! in a certain logical meaning. //! //! As such, commands in Event Sourcing will **produce** Domain Events. //! //! Aggregates should provide a way to **fold** Domain Events on the //! current value of the state, to produce the next state. //! //! ## Aggregate in `eventually` //! //! `eventually` supports the Aggregates through the [`Aggregate`] trait. //! //! An [`Aggregate`] allows to: //! * specify the available commands through the [`Command`] associated type, //! usually an `enum`, //! * define how to handle commands through the [`handle`] method, //! * specify the Aggregate's Domain Events through the [`Event`] //! associated type, usually an `enum`, //! * define the transition logic from one state to another by an [`Event`], //! through the [`apply`] method. //! //! An [`Aggregate`] is essentialy an _actor_, which means it should contain //! all the dependencies it needs to execute commands (e.g. repositories, //! external clients, validators, etc...) //! //! Let's take the Orders Management example: //! //! ```rust //! use eventually::Aggregate; //! use futures::future::BoxFuture; //! //! // This is the state of our Order, which contains one or more items, //! // and whether it has been placed or not. //! #[derive(Default)] //! struct OrderState { //! items: Vec<OrderItem>, //! placed: bool, //! } //! //! // This is a single order item, which contains the order SKU, the number //! // of quantities of the same item and the price. //! struct OrderItem { //! sku: String, //! quantity: u32, //! price: f32, //! } //! //! // Let's say we have a catalog of available items in our system. //! // //! // We want to make sure that each item that has been added to the Order //! // is available in the catalog. //! // //! // We're going to use this trait in the Aggregate implementation, //! // when handling events to add OrderItems. //! trait OrderItemsCatalog { //! fn get_item(&self, sku: String) -> BoxFuture<OrderItem>; //! } //! //! // This is the list of all the commands that are available on our Aggregate. //! enum OrderCommand { //! // Make the order final and place it to the production line. //! PlaceOrder, //! // Add an OrderItem to the Order, specifying a quantity. //! AddOrderItem { //! sku: String, //! quantity: u32, //! }, //! // Remove an OrderItem from the Order: the item is removed //! // when the quantity in the Order is less or equal than //! // the quantity asked to be removed by the command. //! RemoveOrderItem { //! sku: String, //! quantity: u32, //! }, //! } //! //! // This is the list of all the domain events defined on the Order aggregate. //! enum OrderEvent { //! // The list of OrderItems is updated with the specified value. //! OrderItemsUpdated { //! items: Vec<OrderItem>, //! }, //! // Marks the order as placed. //! OrderPlaced, //! } //! //! // This is our Aggregate actor, which will contain all the necessary //! // dependencies for handling commands. //! // //! // In this case, it will only contain the OrderItemCatalog. //! struct OrderAggregate { //! catalog: std::sync::Arc<dyn OrderItemsCatalog>, //! } //! //! // Implementation for the Aggregate trait. //! impl Aggregate for OrderAggregate { //! type Id = u64; //! type State = OrderState; //! type Event = OrderEvent; //! type Command = OrderCommand; //! type Error = std::convert::Infallible; // This should be a meaningful error. //! //! fn apply(state: Self::State, event: Self::Event) -> Result<Self::State, Self::Error> { //! unimplemented!() //! } //! //! fn handle<'a, 's: 'a>( //! &'a self, //! id: &'s Self::Id, //! state: &'s Self::State, //! command: Self::Command, //! ) -> BoxFuture<'a, Result<Option<Vec<Self::Event>>, Self::Error>> //! where //! Self: Sized //! { //! unimplemented!() //! } //! } //! ``` //! //! ### Note on [`State`] //! //! An [`Aggregate`]'s [`State`] type needs to implement the `Default` trait, //! to always have an initial state representation. //! //! This is very important for functional _folding_ of [`Event`]s //! done by [`apply`]. //! //! A common type used in [`State`] is `Option<StateType>`, where //! `StateType` doesn't usually implement `Default`. This is to represent //! a nullable state before the first command is received. //! //! Given the common use-case, `eventually` has included support for //! the [`Optional`] aggregate trait, where you can use `StateType` //! directly in the `State` associated type. //! //! [`Optional`] is compatible with the [`Aggregate`] trait through //! the [`as_aggregate`] method, or the [`optional::AsAggregate`] //! newtype adapter. //! //! ### Interacting with Aggregates using `AggregateRoot` //! //! Interaction with Aggregates is doable through an [`AggregateRoot`]. //! //! An [`AggregateRoot`] represents a specific Aggregate instance, //! by managing its [`State`] and the access to submit commands. //! //! Access to an [`AggregateRoot`] is obtainable in two ways: //! 1. Through the [`AggregateRootBuilder`], useful for testing //! 2. Through a [`Repository`] instance //! //! More on the [`Repository`] in the [module-level documentation](../repository/index.html). //! //! [Aggregate]: https://martinfowler.com/bliki/DDD_Aggregate.html //! [`Aggregate`]: trait.Aggregate.html //! [`Command`]: trait.Aggregate.html#associatedType.Command //! [`Event`]: trait.Aggregate.html#associatedType.Event //! [`State`]: trait.Aggregate.html#associatedType.State //! [`handle`]: trait.Aggregate.html#tymethod.handle //! [`apply`]: trait.Aggregate.html#tymethod.apply //! [`Optional`]: trait.Optional.html //! [`as_aggregate`]: trait.Optional.html#method.as_aggregate //! [`optional::AsAggregate`]: ../optional/struct.AsAggregate.html //! [`AggregateRoot`]: struct.AggregateRoot.html //! [`AggregateRootBuilder`]: struct.AggregateRootBuilder.html //! [`Repository`]: struct.Repository.html pub use eventually_core::aggregate::*; pub use eventually_core::repository::Repository; pub use eventually_util::optional::Aggregate as Optional; } pub mod versioning { //! Module containing support for Optimistic Concurrency using //! Versioning. //! //! In the future, it will contain support for conflict resolution //! caused by concurrent writes scenarios. pub use eventually_core::versioning::*; } pub mod repository { //! Module containing Repository implementation to retrieve, //! save and delete Aggregates. //! //! ## Repository and Aggregates //! //! As described in the [Interacting with Aggregates using `AggregateRoot`] //! section in the `aggregate` module-level documentation, in order to //! interact with an Aggregate instance you need to use an [`AggregateRoot`]. //! //! To get an [`AggregateRoot`], you can use a [`Repository`] instance. //! //! The [`Repository`] allows to **retrieve**, **save** and **remove** //! specific Aggregate instances, by using an underlying [`EventStore`] //! implementation that handles the Aggregate's events. //! //! A [`Repository`] will **always** return an [`AggregateRoot`] instance //! on read, whether or not events are present in the [`EventStore`]. //! //! Use the [`Repository`] to implement your bounded-context application logic, //! for example in HTTP or RPC handlers. //! //! [Interacting with Aggregates using `AggregateRoot`]: ../aggregate/index.html#interacting-with-aggregates-using-aggregateroot //! [`AggregateRoot`]: ../aggregate/struct.AggregateRoot.html //! [`Repository`]: struct.Repository.html //! [`EventStore`]: ../store/trait.EventStore.html pub use eventually_core::repository::*; } pub mod store { //! Module containing support for the Event Store. //! //! ## Event Store and `eventually` //! //! An Event Store is an ordered, append-only log of many Domain Events //! related to one or more Aggregate instances. //! //! The Domain Events committed to the Event Store can be streamed back into //! the application to load the latest value of an Aggregate state, //! by using the concept of Event Streams. //! //! Since Domain Events in the Store are ordered both globally and //! on an Aggregate-instance basis, the Event Stream can either be global //! or related to a single Aggregate. //! //! `eventually` adds support for the Event Store through the [`EventStore`] //! trait. //! //! You rarely need to use the [`EventStore`] directly when writing your //! application, since `eventually` exposes multiple utilities that //! instrument the usage of the store for you. For example: //! * [`Repository`] for retrieving, saving and deleting Aggregates //! * [`Projector`] to run [`Projection`]s (check out the [`projection` module documentation]) //! //! [`EventStore`]: trait.EventStore.html //! [`Repository`]: ../repository/struct.Repository.html //! [`Projector`]: ../struct.Projector.html //! [`Projection`]: ../trait.Projection.html //! [`projection` module documentation]: ../projection/index.html pub use eventually_core::store::*; } pub mod subscription { //! Module containing support for Subscriptions to Events coming //! from the Event Store. //! //! ## What are Subscriptions? //! //! Subscriptions, as the name suggest, allows to subscribe to changes //! in the Event Store. Essentialy, Subscriptions receive Events //! when they get committed to the Store. //! //! This allows for near real-time processing of multiple things, such as //! publishing committed events on a message broker, or running **projections** //! (more on that on [`Projection` documentation]). //! //! ## Subscriptions in `eventually` //! //! ### `EventSubscriber` trait //! //! In order to subscribe to Events, `eventually` exposes the [`EventSubscriber`] //! trait, usually implemented by [`EventStore`] implementations. //! //! An [`EventSubscriber`] opens an _endless_ [`EventStream`], that gets //! closed only at application shutdown, or if the stream gets explicitly dropped. //! //! The [`EventStream`] receives all the **new Events** committed //! to the [`EventStore`]. //! //! ### `Subscription` trait //! //! The [`Subscription`] trait represent an ongoing subscription //! to Events coming from an [`EventStream`], as described above. //! //! Similarly to the [`EventSubscriber`], a [`Subscription`] //! returns an _endless_ stream of Events called [`SubscriptionStream`]. //! //! However, [`Subscription`]s are **stateful**: they save the latest //! Event sequence number that has been processed through the [`SubscriptionStream`], //! by using the [`checkpoint`] method. Later, the [`Subscription`] can be //! restarted from where it was left off using the [`resume`] method. //! //! This module exposes a simple [`Subscription`] implementation: //! [`Transient`], for in-memory, one-off subscriptions. //! //! For a long-running [`Subscription`] implementation, //! take a look at persisted subscriptions, such as [`postgres::subscription::Persisted`]. //! //! [`Projection` documentation]: ../trait.Projection.html //! [`EventSubscriber`]: trait.EventSubscriber.html //! [`EventStore`]: ../store/trait.EventStore.html //! [`EventStream`]: type.EventStream.html //! [`Subscription`]: trait.Subscription.html //! [`SubscriptionStream`]: type.SubscriptionStream.html //! [`checkpoint`]: trait.Subscription.html#tymethod.checkpoint //! [`resume`]: trait.Subscription.html#tymethod.resume //! [`Transient`]: struct.Transient.html //! [`postgres::subscription::Persisted`]: ../postgres/subscription/struct.Persisted.html pub use eventually_core::subscription::*; } pub mod optional { //! Module for the Aggregate extension trait using an `Option` state. //! //! For more information, take a look at the [relevant `aggregate` documentation section] //! on the [`Optional`] aggregate trait. //! //! [relevant `aggregate` documentation section]: ../aggregate/index.html#note-on-state //! [`Optional`]: trait.Aggregate.html pub use eventually_util::optional::*; } pub mod inmemory { //! Module containing utilities using in-memory backend strategy. pub use eventually_util::inmemory::*; } pub mod sync { //! Module containing the synchronization primitives used by the library. pub use eventually_util::sync::*; } #[cfg(feature = "postgres")] pub mod postgres { //! Module containing Event Store support using PostgreSQL backend. pub use eventually_postgres::*; }