Skip to main content

angzarr_client/router/
dispatch.rs

1//! Dispatch helpers for routing events/commands by type URL.
2
3/// Helper macro for dispatching events by type URL suffix.
4///
5/// Simplifies the common pattern of matching event type URLs and delegating
6/// to handler methods.
7///
8/// # Example
9///
10/// ```rust,ignore
11/// use angzarr_client::dispatch_event;
12///
13/// impl SagaDomainHandler for OrderSagaHandler {
14///     fn execute(
15///         &self,
16///         source: &EventBook,
17///         event: &Any,
18///         destinations: &[EventBook],
19///     ) -> CommandResult<Vec<CommandBook>> {
20///         dispatch_event!(event, source, destinations, {
21///             "OrderCompleted" => self.handle_completed,
22///             "OrderCancelled" => self.handle_cancelled,
23///         })
24///     }
25/// }
26/// ```
27///
28/// # Variants
29///
30/// ## For saga execute (source + destinations)
31/// ```rust,ignore
32/// dispatch_event!(event, source, destinations, {
33///     "Suffix" => handler_method,
34/// })
35/// ```
36///
37/// ## For saga prepare (source only, returns Vec<Cover>)
38/// ```rust,ignore
39/// dispatch_event!(event, source, {
40///     "Suffix" => prepare_method,
41/// })
42/// ```
43#[macro_export]
44macro_rules! dispatch_event {
45    // Saga execute variant: (event, source, destinations, handlers)
46    ($event:expr, $source:expr, $destinations:expr, { $($suffix:literal => $handler:expr),* $(,)? }) => {{
47        let type_url = &$event.type_url;
48        $(
49            if type_url.ends_with($suffix) {
50                return $handler($source, $event, $destinations);
51            }
52        )*
53        Ok(vec![])
54    }};
55
56    // Saga prepare variant: (event, source, handlers) -> Vec<Cover>
57    ($event:expr, $source:expr, { $($suffix:literal => $handler:expr),* $(,)? }) => {{
58        let type_url = &$event.type_url;
59        $(
60            if type_url.ends_with($suffix) {
61                return $handler($source, $event);
62            }
63        )*
64        vec![]
65    }};
66}
67
68/// Helper macro for dispatching commands by type URL suffix.
69///
70/// Similar to `dispatch_event!` but for command handler handlers.
71///
72/// # Example
73///
74/// ```rust,ignore
75/// use angzarr_client::dispatch_command;
76///
77/// impl CommandHandlerDomainHandler for PlayerHandler {
78///     fn handle(
79///         &self,
80///         cmd: &CommandBook,
81///         payload: &Any,
82///         state: &PlayerState,
83///         seq: u32,
84///     ) -> CommandResult<EventBook> {
85///         dispatch_command!(payload, cmd, state, seq, {
86///             "RegisterPlayer" => self.handle_register,
87///             "DepositFunds" => self.handle_deposit,
88///         })
89///     }
90/// }
91/// ```
92#[macro_export]
93macro_rules! dispatch_command {
94    ($payload:expr, $cmd:expr, $state:expr, $seq:expr, { $($suffix:literal => $handler:expr),* $(,)? }) => {{
95        let type_url = &$payload.type_url;
96        $(
97            if type_url.ends_with($suffix) {
98                return $handler($cmd, $payload, $state, $seq);
99            }
100        )*
101        Err($crate::CommandRejectedError::new(format!("Unknown command type: {}", type_url)))
102    }};
103}
104
105// Macros are exported at crate level via #[macro_export]
106// Re-exported from router module for documentation purposes