mod_events/
async_support.rs

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