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}