discern/
macros.rs

1//! The `macros` module provides convenient macros for creating and registering command and query buses.
2//!
3//! This module includes macros for initializing `CommandBus` and `QueryBus` instances with their respective
4//! handlers, as well as macros for creating and registering command and query handler registries.
5//!
6//! Key macros:
7//!
8//! - [command_bus](crate::command_bus): Creates a `CommandBus` and registers handlers.
9//! - [command_registry](crate::command_registry): Creates a `CommandHandlerRegistry` and registers handlers.
10//! - [query_bus](crate::query_bus): Creates a `QueryBus` and registers handlers.
11//! - [query_registry](crate::query_registry): Creates a `QueryHandlerRegistry` and registers handlers.
12
13/// A macro for creating a `CommandBus` instance.
14///
15/// This macro provides a convenient way to initialize a `CommandBus` and register multiple
16/// command handlers at once.
17///
18/// # Usage
19///
20/// You can use this macro in two ways:
21///
22/// 1. **Providing only handlers:**
23///
24/// ```
25/// # let rt = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap();
26/// # rt.block_on(async {
27/// # use discern::command::Command;
28/// # use discern::async_trait;
29/// # use discern::command::CommandHandler;
30/// #
31/// # #[derive(Debug)]
32/// # enum CreateUserError {
33/// #    UsernameAlreadyExists,
34/// #    EmailAlreadyExists,
35/// # }
36/// #
37/// # #[derive(Debug)]
38/// # struct CreateUserCommand {
39/// #    username: String,
40/// #    email: String,
41/// # }
42/// #
43/// # impl Command for CreateUserCommand {
44/// #   // The identifier of the newly created user.
45/// #   type Metadata = u64;
46/// #   // The error type that is returned if the command fails.
47/// #   type Error = CreateUserError;
48/// # }
49/// #
50/// # struct CreateUserCommandHandler;
51/// #
52/// # #[async_trait]
53/// # impl CommandHandler<CreateUserCommand> for CreateUserCommandHandler {
54/// #    async fn handle(&self, command: CreateUserCommand) -> Result<u64, CreateUserError> {
55/// #       // Create a new user.
56/// #       Ok(1)
57/// #   }
58/// # }
59/// use discern::command_bus;
60///
61/// let command_bus = command_bus! {
62///    CreateUserCommandHandler { /* ... */ },
63/// };
64/// #
65/// #   let command = CreateUserCommand {
66/// #       username: "alice".to_string(),
67/// #       email: "alice@localhost".to_string(),
68/// #   };
69/// #
70/// #   let result = command_bus.dispatch(command).await;
71/// #   match result {
72/// #       Ok(user_id) => {
73/// #           assert_eq!(user_id, 1);
74/// #           println!("User created with id: {}", user_id);
75/// #       },
76/// #       Err(err) => {
77/// #           assert!(false);
78/// #           eprintln!("Failed to create user: {:?}", err);
79/// #       }
80/// #   }
81/// # });
82/// ```
83///
84/// This assumes that the types of the handlers can be inferred automatically.
85///
86/// 2. **Providing type-handler pairs:**
87///
88/// ```
89/// # let rt = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap();
90/// # rt.block_on(async {
91/// # use discern::command::Command;
92/// # use discern::async_trait;
93/// # use discern::command::CommandHandler;
94/// #
95/// # #[derive(Debug)]
96/// # enum CreateUserError {
97/// #    UsernameAlreadyExists,
98/// #    EmailAlreadyExists,
99/// # }
100/// #
101/// # #[derive(Debug)]
102/// # struct CreateUserCommand {
103/// #    username: String,
104/// #    email: String,
105/// # }
106/// #
107/// # impl Command for CreateUserCommand {
108/// #   // The identifier of the newly created user.
109/// #   type Metadata = u64;
110/// #   // The error type that is returned if the command fails.
111/// #   type Error = CreateUserError;
112/// # }
113/// #
114/// # struct CreateUserCommandHandler;
115/// #
116/// # #[async_trait]
117/// # impl CommandHandler<CreateUserCommand> for CreateUserCommandHandler {
118/// #    async fn handle(&self, command: CreateUserCommand) -> Result<u64, CreateUserError> {
119/// #       // Create a new user.
120/// #       Ok(1)
121/// #   }
122/// # }
123/// use discern::command_bus;
124///
125/// let command_bus = command_bus! {
126///    CreateUserCommand => CreateUserCommandHandler { /* ... */ },
127/// };
128/// #
129/// #   let command = CreateUserCommand {
130/// #       username: "alice".to_string(),
131/// #       email: "alice@localhost".to_string(),
132/// #   };
133/// #
134/// #   let result = command_bus.dispatch(command).await;
135/// #   match result {
136/// #       Ok(user_id) => {
137/// #           assert_eq!(user_id, 1);
138/// #           println!("User created with id: {}", user_id);
139/// #       },
140/// #       Err(err) => {
141/// #           assert!(false);
142/// #           eprintln!("Failed to create user: {:?}", err);
143/// #       }
144/// #   }
145/// # });
146/// ```
147/// This explicitly specifies the command type associated with each handler.
148///
149/// # See Also
150///
151/// - [CommandBus](crate::command::CommandBus)
152#[macro_export]
153macro_rules! command_bus {
154        () => {{
155            $crate::command::CommandBus::new($crate::registry::CommandHandlerRegistry::new())
156        }};
157        ($($handler:expr),*$(,)?) => {{
158            let mut command_handler_registry = $crate::registry::CommandHandlerRegistry::new();
159            $(command_handler_registry.register($handler);)*
160            $crate::command::CommandBus::new(command_handler_registry)
161        }};
162        ($($command:ty => $handler:expr),*$(,)?) => {{
163            let mut command_handler_registry = $crate::registry::CommandHandlerRegistry::new();
164            $(command_handler_registry.register::<$command>($handler);)*
165            $crate::command::CommandBus::new(command_handler_registry)
166        }};
167    }
168
169/// A macro for creating a `CommandHandlerRegistry` instance.
170///
171/// This macro provides a convenient way to initialize a `CommandHandlerRegistry` and register multiple
172/// command handlers at once.
173///
174/// # Usage
175///
176/// You can use this macro in two ways:
177///
178/// 1. **Providing only handlers:**
179///
180/// ```
181/// # let rt = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap();
182/// # rt.block_on(async {
183/// # use discern::command::Command;
184/// # use discern::async_trait;
185/// # use discern::command::CommandHandler;
186/// #
187/// # #[derive(Debug)]
188/// # enum CreateUserError {
189/// #    UsernameAlreadyExists,
190/// #    EmailAlreadyExists,
191/// # }
192/// #
193/// # #[derive(Debug)]
194/// # struct CreateUserCommand {
195/// #    username: String,
196/// #    email: String,
197/// # }
198/// #
199/// # impl Command for CreateUserCommand {
200/// #   // The identifier of the newly created user.
201/// #   type Metadata = u64;
202/// #   // The error type that is returned if the command fails.
203/// #   type Error = CreateUserError;
204/// # }
205/// #
206/// # struct CreateUserCommandHandler;
207/// #
208/// # #[async_trait]
209/// # impl CommandHandler<CreateUserCommand> for CreateUserCommandHandler {
210/// #    async fn handle(&self, command: CreateUserCommand) -> Result<u64, CreateUserError> {
211/// #       // Create a new user.
212/// #       Ok(1)
213/// #   }
214/// # }
215/// use discern::command_registry;
216///
217/// let command_registry = command_registry! {
218///    CreateUserCommandHandler { /* ... */ },
219/// };
220/// # });
221/// ```
222///
223/// This assumes that the types of the handlers can be inferred automatically.
224///
225/// 2. **Providing type-handler pairs:**
226///
227/// ```
228/// # let rt = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap();
229/// # rt.block_on(async {
230/// # use discern::command::Command;
231/// # use discern::async_trait;
232/// # use discern::command::CommandHandler;
233/// #
234/// # #[derive(Debug)]
235/// # enum CreateUserError {
236/// #    UsernameAlreadyExists,
237/// #    EmailAlreadyExists,
238/// # }
239/// #
240/// # #[derive(Debug)]
241/// # struct CreateUserCommand {
242/// #    username: String,
243/// #    email: String,
244/// # }
245/// #
246/// # impl Command for CreateUserCommand {
247/// #   // The identifier of the newly created user.
248/// #   type Metadata = u64;
249/// #   // The error type that is returned if the command fails.
250/// #   type Error = CreateUserError;
251/// # }
252/// #
253/// # struct CreateUserCommandHandler;
254/// #
255/// # #[async_trait]
256/// # impl CommandHandler<CreateUserCommand> for CreateUserCommandHandler {
257/// #    async fn handle(&self, command: CreateUserCommand) -> Result<u64, CreateUserError> {
258/// #       // Create a new user.
259/// #       Ok(1)
260/// #   }
261/// # }
262/// use discern::command_registry;
263///
264/// let command_registry = command_registry! {
265///    CreateUserCommand => CreateUserCommandHandler { /* ... */ },
266/// };
267/// # });
268/// ```
269/// This explicitly specifies the command type associated with each handler.
270///
271/// # See Also
272///
273/// - [CommandHandlerRegistry](crate::registry::CommandHandlerRegistry)
274#[macro_export]
275macro_rules! command_registry {
276        () => {{
277            $crate::command::CommandHandlerRegistry::new()
278        }};
279        ($($handler:expr),*$(,)?) => {{
280            let mut command_handler_registry = $crate::registry::CommandHandlerRegistry::new();
281            $(command_handler_registry.register($handler);)*
282            command_handler_registry
283        }};
284        ($($command:ty => $handler:expr),*$(,)?) => {{
285            let mut command_handler_registry = $crate::registry::CommandHandlerRegistry::new();
286            $(command_handler_registry.register::<$command>($handler);)*
287            command_handler_registry
288        }};
289    }
290/// A macro for creating a `QueryBus` instance.
291///
292/// This macro provides a convenient way to initialize a `QueryBus` and register multiple
293/// query handlers at once.
294///
295/// # Usage
296///
297/// You can use this macro in two ways:
298///
299/// 1. **Providing only handlers:**
300///
301/// ```
302/// # let rt = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap();
303/// # rt.block_on(async {
304/// # use discern::query::Query;
305/// # use discern::async_trait;
306/// # use discern::query::QueryHandler;
307/// #
308/// # #[derive(Debug)]
309/// # struct GetUserQuery {
310/// #     user_id: u64,
311/// # }
312/// #
313/// # impl Query for GetUserQuery {
314/// #     type Output = String;
315/// #     type Error = std::io::Error;
316/// # }
317/// #
318/// # struct GetUserQueryHandler;
319/// #
320/// # #[async_trait]
321/// # impl QueryHandler<GetUserQuery> for GetUserQueryHandler {
322/// #     async fn handle(&self, query: GetUserQuery) -> Result<String, std::io::Error> {
323/// #         Ok("Alice".to_string())
324/// #     }
325/// # }
326/// use discern::query_bus;
327///
328/// let query_bus = query_bus! {
329///     GetUserQueryHandler { /* ... */ },
330/// };
331/// #
332/// #   let query = GetUserQuery { user_id: 1 };
333/// #   let result = query_bus.dispatch(query).await;
334/// #   match result {
335/// #       Ok(name) => println!("User name: {}", name),
336/// #       Err(err) => eprintln!("Failed to get user: {:?}", err),
337/// #   }
338/// # });
339/// ```
340///
341/// This assumes that the types of the handlers can be inferred automatically.
342///
343/// 2. **Providing type-handler pairs:**
344///
345/// ```
346/// # let rt = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap();
347/// # rt.block_on(async {
348/// # use discern::query::Query;
349/// # use discern::async_trait;
350/// # use discern::query::QueryHandler;
351/// #
352/// # #[derive(Debug)]
353/// # struct GetUserQuery {
354/// #     user_id: u64,
355/// # }
356/// #
357/// # impl Query for GetUserQuery {
358/// #     type Output = String;
359/// #     type Error = std::io::Error;
360/// # }
361/// #
362/// # struct GetUserQueryHandler;
363/// #
364/// # #[async_trait]
365/// # impl QueryHandler<GetUserQuery> for GetUserQueryHandler {
366/// #     async fn handle(&self, query: GetUserQuery) -> Result<String, std::io::Error> {
367/// #         Ok("Alice".to_string())
368/// #     }
369/// # }
370/// use discern::query_bus;
371///
372/// let query_bus = query_bus! {
373///     GetUserQuery => GetUserQueryHandler { /* ... */ },
374/// };
375/// #
376/// #   let query = GetUserQuery { user_id: 1 };
377/// #   let result = query_bus.dispatch(query).await;
378/// #   match result {
379/// #       Ok(name) => println!("User name: {}", name),
380/// #       Err(err) => eprintln!("Failed to get user: {:?}", err),
381/// #   }
382/// # });
383/// ```
384///
385/// This explicitly specifies the query type associated with each handler.
386///
387/// # See Also
388///
389/// - [QueryBus](crate::query::QueryBus)
390#[macro_export]
391macro_rules! query_bus {
392        () => {{
393            $crate::query::QueryBus::new($crate::registry::QueryHandlerRegistry::new())
394        }};
395        ($($handler:expr),*$(,)?) => {{
396            let mut query_handler_registry = $crate::registry::QueryHandlerRegistry::new();
397            $(query_handler_registry.register($handler);)*
398            $crate::query::QueryBus::new(query_handler_registry)
399        }};
400        ($($query:ty => $handler:expr),*$(,)?) => {{
401            let mut query_handler_registry = $crate::registry::QueryHandlerRegistry::new();
402            $(query_handler_registry.register::<$query>($handler);)*
403            $crate::query::QueryBus::new(query_handler_registry)
404        }};
405    }
406
407/// A macro for creating a `QueryHandlerRegistry` instance.
408///
409/// This macro provides a convenient way to initialize a `QueryHandlerRegistry` and register multiple
410/// query handlers at once.
411///
412/// # Usage
413///
414/// You can use this macro in two ways:
415///
416/// 1. **Providing only handlers:**
417///
418/// ```
419/// # let rt = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap();
420/// # rt.block_on(async {
421/// # use discern::query::Query;
422/// # use discern::async_trait;
423/// # use discern::query::QueryHandler;
424/// #
425/// # #[derive(Debug)]
426/// # struct GetUserQuery {
427/// #     user_id: u64,
428/// # }
429/// #
430/// # impl Query for GetUserQuery {
431/// #     type Output = String;
432/// #     type Error = std::io::Error;
433/// # }
434/// #
435/// # struct GetUserQueryHandler;
436/// #
437/// # #[async_trait]
438/// # impl QueryHandler<GetUserQuery> for GetUserQueryHandler {
439/// #     async fn handle(&self, query: GetUserQuery) -> Result<String, std::io::Error> {
440/// #         Ok("Alice".to_string())
441/// #     }
442/// # }
443/// use discern::query_registry;
444///
445/// let query_registry = query_registry! {
446///     GetUserQueryHandler { /* ... */ },
447/// };
448/// # });
449/// ```
450///
451/// This assumes that the types of the handlers can be inferred automatically.
452///
453/// 2. **Providing type-handler pairs:**
454///
455/// ```
456/// # let rt = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap();
457/// # rt.block_on(async {
458/// # use discern::query::Query;
459/// # use discern::async_trait;
460/// # use discern::query::QueryHandler;
461/// #
462/// # #[derive(Debug)]
463/// # struct GetUserQuery {
464/// #     user_id: u64,
465/// # }
466/// #
467/// # impl Query for GetUserQuery {
468/// #     type Output = String;
469/// #     type Error = std::io::Error;
470/// # }
471/// #
472/// # struct GetUserQueryHandler;
473/// #
474/// # #[async_trait]
475/// # impl QueryHandler<GetUserQuery> for GetUserQueryHandler {
476/// #     async fn handle(&self, query: GetUserQuery) -> Result<String, std::io::Error> {
477/// #         Ok("Alice".to_string())
478/// #     }
479/// # }
480/// use discern::query_registry;
481///
482/// let query_registry = query_registry! {
483///     GetUserQuery => GetUserQueryHandler { /* ... */ },
484/// };
485/// # });
486/// ```
487///
488/// This explicitly specifies the query type associated with each handler.
489///
490/// # See Also
491///
492/// - [QueryHandlerRegistry](crate::registry::QueryHandlerRegistry)
493#[macro_export]
494macro_rules! query_registry {
495        () => {{
496            $crate::query::QueryHandlerRegistry::new()
497        }};
498        ($($handler:expr),*$(,)?) => {{
499            let mut query_handler_registry = $crate::registry::QueryHandlerRegistry::new();
500            $(query_handler_registry.register($handler);)*
501            query_handler_registry
502        }};
503        ($($query:ty => $handler:expr),*$(,)?) => {{
504            let mut query_handler_registry = $crate::registry::QueryHandlerRegistry::new();
505            $(query_handler_registry.register::<$query>($handler);)*
506            query_handler_registry
507        }};
508    }