ruva_core/bus_components/handler/command/
uow.rs

1use 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			// TODO This code only processes events that can be externally notified. Need to develop
42			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    // Case with custom handler function
97    (
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    // Default case
110    (
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}