ruva_core/bus_components/handler/command/
uow.rs1use super::*;
2
3pub trait TUnitOfWorkCommandHandler: Send + Sync {
4 type Dependency;
5 fn destruct(self) -> Self::Dependency;
6}
7
8impl<D1, D2> TUnitOfWorkCommandHandler for CommandHandler<(D1, D2)>
9where
10 D1: crate::prelude::TCommand,
11 D2: crate::prelude::TSetCurrentEvents + crate::prelude::TUnitOfWork,
12{
13 type Dependency = (D1, D2);
14
15 fn destruct(self) -> Self::Dependency {
16 self.0
17 }
18}
19
20impl<T, R, E, D1, D2> TCommandService<R, E> for T
21where
22 R: ApplicationResponse,
23 E: ApplicationError + std::convert::From<crate::responses::BaseError> + std::convert::Into<BaseError> + Clone,
24 D1: TCommand + for<'a> TGetHandler<&'a mut D2, Result<R, E>>,
25 D2: TSetCurrentEvents + TUnitOfWork,
26 T: TUnitOfWorkCommandHandler<Dependency = (D1, D2)>,
27{
28 async fn execute(self) -> Result<R, E> {
29 let (cmd, mut dep) = self.destruct();
30
31 dep.begin().await?;
32
33 let result = (D1::get_handler())(cmd, &mut dep).await;
34 match result {
35 Ok(val) => {
36 dep.commit().await?;
37 dep.close().await;
38
39 Ok(val)
40 }
41 Err(err) => {
43 dep.rollback().await?;
44 dep.close().await;
45
46 if let BaseError::StopSentinelWithEvent(event) = err.clone().into() {
47 dep.set_current_events(vec![event.clone()].into());
48 dep.process_internal_events().await?;
49 dep.process_external_events().await?;
50 Err(BaseError::StopSentinelWithEvent(event).into())
51 } else {
52 Err(err)
53 }
54 }
55 }
56 }
57}
58
59#[macro_export]
60#[doc(hidden)]
61macro_rules! __register_uow_services_internal {
62 (
63 $response:ty,
64 $error:ty,
65 $h:expr,
66
67 $(
68 $command:ty => $handler:expr
69 ),*
70 ) => {
71 use ruva::TUnitOfWorkCommandHandler;
72 type ApplicationResult = std::result::Result<$response,$error>;
73
74 $(
75 impl<'a> ruva::TGetHandler<&'a mut ::ruva::Context, ApplicationResult> for $command {
76 fn get_handler() -> impl ::ruva::AsyncFunc<$command, &'a mut ::ruva::Context, ApplicationResult > {
77 $handler
78 }
79 }
80
81 impl ::ruva::TMessageBus<$response,$error,$command> for ::ruva::MessageBus{
82 fn command_handler(
83 &self,
84 context_manager: ruva::AtomicContextManager,
85 cmd: $command,
86 ) -> impl ::ruva::TCommandService<$response, $error> {
87 $h(::ruva::CommandHandler((cmd, ::ruva::Context::new(context_manager))))
88 }
89 }
90 )*
91 };
92}
93
94#[macro_export]
95macro_rules! register_uow_services {
96 (
98 $response:ty,
99 $error:ty,
100 $h:expr,
101
102 $(
103 $command:ty => $handler:expr
104 ),*
105 ) => {
106 ruva::__register_uow_services_internal!($response, $error, $h, $($command => $handler),*);
107 };
108
109 (
111 $response:ty,
112 $error:ty,
113
114 $(
115 $command:ty => $handler:expr
116 ),*
117 ) => {
118 ruva::__register_uow_services_internal!($response, $error, ::std::convert::identity, $($command => $handler),*);
119 };
120}