mediator_sys/mediator/asynchronous/contextaware/contextaware.rs
1use std::sync::mpsc::TryRecvError;
2
3use async_std::sync::Mutex;
4use async_trait::async_trait;
5use std::fmt::Debug;
6
7use crate::asynchronous::basic::BasicAsyncMediator;
8
9use super::*;
10
11/// Context aware async mediator for asynchronous environments with events of type `Ev`.
12///
13/// Uses an underlying [`BasicAsyncMediator`] for base functionality
14/// and a `Mutex` to store the user-defined dependency `Dep`.
15///
16/// # Examples
17///
18/// Basic usage:
19///
20/// ```
21/// use mediator_sys::asynchronous::contextaware::*;
22/// use std::sync::Arc;
23/// use async_trait::async_trait;
24/// use async_std;
25///
26/// #[derive(Debug, Clone)]
27/// enum MyEvent {
28/// One,
29/// Two
30/// }
31///
32/// #[derive(Debug, Default)]
33/// struct MyContext(Arc<u32>);
34///
35/// struct Request(u32);
36///
37/// #[async_trait]
38/// impl CxAwareAsyncRequestHandler<MyContext, Request, MyEvent> for CxAwareAsyncMediator<MyContext, MyEvent> {
39/// async fn handle(&self, req: Request, dep: &MyContext) {
40/// let my_context: u32 = *dep.0;
41/// match req.0 {
42/// 1 => self.publish(MyEvent::One).await,
43/// 2 => self.publish(MyEvent::Two).await,
44/// _ => ()
45/// };
46/// }
47/// }
48///
49/// async_std::task::block_on(async {
50/// let mediator = CxAwareAsyncMediator::<MyContext, MyEvent>::builder()
51/// .add_listener(move |ev| {
52/// /* Your listening logic */
53/// })
54/// .add_listener(move |ev| {
55/// /* Your listening logic */
56/// })
57/// .add_dependency(MyContext::default())
58/// .build()
59/// .unwrap();
60///
61/// mediator.send(Request(1)).await;
62/// mediator.next().await.ok();
63/// });
64///
65#[cfg(feature = "async")]
66#[derive(Debug)]
67pub struct CxAwareAsyncMediator<Dep, Ev>
68where
69 Dep: Debug,
70 Ev: Debug,
71{
72 pub(crate) basic: BasicAsyncMediator<Ev>,
73 pub(crate) dep: Mutex<Dep>,
74}
75
76#[async_trait]
77impl<Dep, Ev> AsyncMediatorInternal<Ev> for CxAwareAsyncMediator<Dep, Ev>
78where
79 Dep: Debug + Send,
80 Ev: Debug + Send,
81{
82 /// Publishes an event `Ev` asynchronously.
83 ///
84 /// This method instructs the underlying [`BasicAsyncMediator`]
85 /// to publish a user-defined event.
86 ///
87 /// It should be used within [`CxAwareAsyncRequestHandler::handle()`].
88 ///
89 /// You need to await the `Future` using `.await`.
90 ///
91 /// # Examples
92 ///
93 /// Basic usage:
94 ///
95 /// ```
96 /// use mediator_sys::asynchronous::contextaware::*;
97 /// use async_trait::async_trait;
98 /// use std::sync::Arc;
99 ///
100 /// #[derive(Debug, Clone)]
101 /// enum MyEvent {
102 /// One,
103 /// Two
104 /// }
105 ///
106 /// #[derive(Debug, Default)]
107 /// struct MyContext(Arc<u32>);
108 ///
109 /// struct Request(u32);
110 ///
111 /// #[async_trait]
112 /// impl CxAwareAsyncRequestHandler<MyContext, Request, MyEvent> for CxAwareAsyncMediator<MyContext, MyEvent> {
113 /// async fn handle(&self, req: Request, dep: &MyContext) {
114 /// let my_context: u32 = *dep.0;
115 /// match req.0 {
116 /// 1 => self.publish(MyEvent::One).await,
117 /// 2 => self.publish(MyEvent::Two).await,
118 /// _ => ()
119 /// };
120 /// }
121 /// }
122 ///
123 async fn publish(&self, event: Ev) {
124 self.basic.publish(event).await
125 }
126}
127
128#[async_trait]
129impl<Dep, Ev> CxAwareAsyncMediatorInternalHandle<Dep, Ev> for CxAwareAsyncMediator<Dep, Ev>
130where
131 Dep: Debug + Send + Sync,
132 Ev: Debug + Send,
133{
134 /// Send a request of type `Req` to the mediator asynchronously.
135 ///
136 /// The request will be processed internally by [`CxAwareAsyncRequestHandler::handle()`].
137 /// This is why it is required to implement [`CxAwareAsyncRequestHandler`] for [`CxAwareAsyncMediator`].
138 /// A `Mutex` will be locked in order to gain access to the context `Dep`.
139 ///
140 /// You need to await the `Future` using `.await`.
141 ///
142 async fn send<Req>(&self, req: Req)
143 where
144 Self: CxAwareAsyncRequestHandler<Dep, Req, Ev>,
145 Req: Send,
146 {
147 let m = self.dep.lock().await;
148 <Self as CxAwareAsyncRequestHandler<Dep, Req, Ev>>::handle(self, req, &m).await
149 }
150}
151
152#[async_trait]
153impl<Dep, Ev> AsyncMediatorInternalNext for CxAwareAsyncMediator<Dep, Ev>
154where
155 Dep: Debug + Send,
156 Ev: Debug + Clone + Send,
157{
158 /// Process the next published event `Ev` asynchronously.
159 ///
160 /// This method instructs the underlying [`BasicAsyncMediator`]
161 /// to process the next event.
162 ///
163 /// See [`BasicAsyncMediator::next()`] for more info.
164 ///
165 /// You need to await the `Future` using `.await`.
166 ///
167 async fn next(&self) -> Result<(), TryRecvError> {
168 self.basic.next().await
169 }
170}