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}