Skip to main content

mod_events/
async_support.rs

1//! Async event support (requires "async" feature)
2
3use crate::{Event, ListenerError, Priority};
4use std::future::Future;
5use std::pin::Pin;
6use std::sync::Arc;
7
8/// Pinned future returned by an async listener.
9pub type AsyncEventResult<'a> =
10    Pin<Box<dyn Future<Output = Result<(), ListenerError>> + Send + 'a>>;
11
12/// Trait for asynchronous event listeners.
13///
14/// This trait is only available when the `async` feature is enabled.
15///
16/// # Example
17///
18/// ```rust
19/// # #[cfg(feature = "async")]
20/// # {
21/// use mod_events::{AsyncEventListener, AsyncEventResult, Event, ListenerError, Priority};
22///
23/// #[derive(Debug, Clone)]
24/// struct UserRegistered {
25///     user_id: u64,
26///     email: String,
27/// }
28///
29/// impl Event for UserRegistered {
30///     fn as_any(&self) -> &dyn std::any::Any {
31///         self
32///     }
33/// }
34///
35/// struct AsyncEmailNotifier;
36///
37/// impl AsyncEventListener<UserRegistered> for AsyncEmailNotifier {
38///     fn handle<'a>(&'a self, event: &'a UserRegistered) -> AsyncEventResult<'a> {
39///         Box::pin(async move {
40///             println!("Async email sent to {}", event.email);
41///             Ok(())
42///         })
43///     }
44/// }
45/// # }
46/// ```
47pub trait AsyncEventListener<T: Event>: Send + Sync {
48    /// Handle the event asynchronously.
49    fn handle<'a>(&'a self, event: &'a T) -> AsyncEventResult<'a>;
50
51    /// Get the priority of this listener.
52    ///
53    /// Higher priority listeners are executed first. Default is
54    /// [`Priority::Normal`].
55    fn priority(&self) -> Priority {
56        Priority::Normal
57    }
58}
59
60/// Internal async listener wrapper.
61type AsyncEventHandler = dyn for<'a> Fn(&'a dyn Event) -> AsyncEventResult<'a> + Send + Sync;
62
63pub(crate) struct AsyncListenerWrapper {
64    pub(crate) handler: Arc<AsyncEventHandler>,
65    pub(crate) priority: Priority,
66    pub(crate) id: usize,
67}
68
69impl std::fmt::Debug for AsyncListenerWrapper {
70    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71        f.debug_struct("AsyncListenerWrapper")
72            .field("priority", &self.priority)
73            .field("id", &self.id)
74            .field("handler", &"<async_function>")
75            .finish()
76    }
77}
78
79impl AsyncListenerWrapper {
80    pub(crate) fn new<T, F, Fut>(listener: F, priority: Priority, id: usize) -> Self
81    where
82        T: Event + 'static,
83        F: Fn(&T) -> Fut + Send + Sync + 'static,
84        Fut: Future<Output = Result<(), ListenerError>> + Send + 'static,
85    {
86        Self {
87            handler: Arc::new(move |event: &dyn Event| {
88                if let Some(concrete_event) = event.as_any().downcast_ref::<T>() {
89                    Box::pin(listener(concrete_event))
90                } else {
91                    Box::pin(async { Ok(()) })
92                }
93            }),
94            priority,
95            id,
96        }
97    }
98}