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
//! A event-driven framework for writing reliable and scalable system.
//!
//! At a high level, it provides a few major components:
//!
//! * Tools for [core components with traits][event-driven-core],
//! * [Macros][event-driven-macro] for processing events and commands
//!
//! [event-driven-core]: crate::event_driven_core
//! [event-driven-macro]: crate::event_driven_macro
//!
//!
//! # A Tour of Event-Driven-Library
//!
//! Event-Driven-Library consists of a number of modules that provide a range of functionality
//! essential for implementing messagebus-like applications in Rust. In this
//! section, we will take a brief tour, summarizing the major APIs and
//! their uses.
//!
//!
//!
//! ### Registering Command
//!
//! Event-Driven-Library is great for writing applications and handlers that are extensible, and modularic.
//! In Event-Drieven Achitecture, `Command` is a request you are given from enduser whereby user
//! expects to get a return as a result of its processing. Handling `Command` may or may not result in `event`,
//! the result of which is not be directly seen by end user as it is side effect.
//! Therefore, you don't want to string along more than one handler for each `Command`.
//!
//!
//! #### Example
//!
//! ```
//! # const IGNORE_1: &str = stringify! {
//! use event_driven_library::prelude::{init_command_handler, init_event_handler};
//! # };
//! # macro_rules! init_command_handler {
//! # ($($tt:tt)*) => {}
//! # }
//! init_command_handler!(
//! {
//! Command1: CommandHandler1,
//! Command2: CommandHandler2,
//! Command3: CommandHandler3,
//! Command4: CommandHandler4,
//! }
//! );
//! ```
//!
//!
//! ### Registering Event
//!
//! `Event` on the other hand, is a side effect of command processing. You can't predict how many
//! transactions should be processed; for that reason, you have vector of events for each event.
//!
//! #### Example
//!
//! ```
//! # macro_rules! init_event_handler {
//! # ($($tt:tt)*) => {}
//! # }
//! init_event_handler!(
//! {
//! Event1: [
//! EventHandler1,
//! EventHandler2,
//! EventHandler3
//! ],
//! Event2: [
//! EventHandler4 => (mail_sender)
//! ]
//! }
//! );
//! ```
//!
//! ### Dependency Injection
//! As you may have noticed in the example above command handler or event handler may have
//! other dependencies other than message and `Context`(which will be covered later). In this case,
//! You can simply register dependencies by putting attribute on top of free function.
//!
//! #### Example
//!
//! ```ignore
//! #[dependency]
//! pub fn mail_sender() -> Box<dyn std::any::Any> {
//! ...
//! }
//! ```
//!
//! This is great as you can take your mind off static nature of the language.
//!
//!
//! ### Command & Event
//! You can register any general struct with `Command`[Command] Derive Macro as follows:
//! ```ignore
//! #[derive(Command)]
//! pub struct CustomCommand {
//! pub id: i64,
//! pub name: String,
//! }
//! ```
//!
//! Likewise, you can do the same thing for Event:
//! ```ignore
//! #[derive(Serialize, Deserialize, Clone, Message)]
//! #[internally_notifiable]
//! pub struct YourCustomEvent {
//! #[identifier]
//! pub user_id: UserId,
//! pub random_uuid: Uuid,
//! }
//! ```
//! Note that use of `internally_notifiable`(or `externally_notifiable`) and `identifier` is MUST.
//!
//! * `internally_notifiable` is marker to let the system know that the event should be handled
//! within the application
//! * `externally_notifiable` is to leave `OutBox`.
//! * `identifier` is to record aggregate id.
//!
//! [Command]: crate::event_driven_core::message::Command
//! [Message]: crate::event_driven_core::message::Message
//!
//!
//!
//! ### MessageBus
//! `MessageBus`[MessageBus] is central pillar which gets command and gets raised event from
//! `UnitOfWork` and dispatch the event to the right handlers.
//! As this is done only in framework side, the only way you can 'feel' the presence of messagebus is
//! when you invoke it. Everything else is done magically.
//!
//! #### Example
//!
//! ```ignore
//! #[derive(Command)]
//! pub struct TestCommand { // Test Command
//! pub id: i64,
//! pub name: String,
//! }
//!
//! async fn test_func(){
//! let bus = MessageBus::new(command_handler().await, event_handler().await)
//! let command = TestCommand{id:1,name:"Migo".into()}
//! let _ = bus.handle(command).await // Use of command
//! }
//! ```
//!
//! #### Error from MessageBus
//! When command has not yet been regitered, it returns an error - `BaseError::CommandNotFound`
//! Be mindful that bus does NOT return the result of event processing as in distributed event processing.
//!
//! [MessageBus]: crate::event_driven_core::messagebus::MessageBus
extern crate event_driven_core;
extern crate event_driven_macro;
pub mod prelude {
pub use event_driven_core::convert_event;
pub use event_driven_core::event_macros::*;
pub use event_driven_core::message::{Aggregate, Command, Message, MessageMetadata};
pub use event_driven_core::prelude::*;
pub use event_driven_macro::{dependency, Aggregate, ApplicationError, Command, Entity, Message};
}
#[cfg(test)]
mod test_expand {
#[test]
fn entity() {
#[derive(event_driven_macro::Entity, Default)]
struct SomeEntity {
age: i64,
name: String,
}
let entity = SomeEntity::default();
let entity = entity.set_age(10).set_name("MigoLee".to_string());
assert_eq!(entity.age, 10);
assert_eq!(entity.name, "MigoLee".to_string())
}
}
#[cfg(test)]
mod dependency_test {
use event_driven_core::create_dependency;
create_dependency!();
#[event_driven_macro::dependency]
fn test() -> i32 {
let _ = "hello";
0
}
}