1use crate::{BoxFuture, Container, Injectable, Module, ModuleMetadata, Result};
2use futures_util::{StreamExt, stream, stream::BoxStream};
3use std::{
4 any::{Any, TypeId},
5 collections::HashMap,
6 marker::PhantomData,
7 sync::{Arc, RwLock},
8};
9use tokio::sync::broadcast;
10use tokio_stream::wrappers::BroadcastStream;
11use tokio_stream::wrappers::errors::BroadcastStreamRecvError;
12
13const EVENT_BROADCAST_CAPACITY: usize = 256;
15
16#[diagnostic::on_unimplemented(
17 message = "`{Self}` is not an event handler for `{E}`",
18 label = "missing `impl EventHandler<{E}> for {Self}`",
19 note = "add `impl EventHandler<{E}> for {Self}` or use the correct event type in `.event_handler_for::<Event, Handler>()`"
20)]
21pub trait EventHandler<E>: Send + Sync + 'static {
22 fn handle(&self, event: E) -> BoxFuture<'_, Result<()>>;
23}
24
25#[diagnostic::on_unimplemented(
26 message = "`{Self}` cannot be registered with `.event_handler::<{Self}>()` yet",
27 label = "missing `impl RegisterableEventHandler for {Self}`",
28 note = "add `impl RegisterableEventHandler for {Self} {{ type Event = YourEvent; }}` or use `.event_handler_for::<YourEvent, {Self}>()`"
29)]
30pub trait RegisterableEventHandler: Injectable {
31 type Event: Clone + Send + Sync + 'static;
32
33 fn register_into(handler: Arc<Self>, bus: &EventBus) -> Result<()>
34 where
35 Self: Sized + EventHandler<Self::Event>,
36 {
37 bus.register::<Self::Event, Self>(handler)
38 }
39}
40
41trait ErasedHandler: Send + Sync {
42 fn handle_erased(&self, event: &dyn Any) -> BoxFuture<'_, Result<()>>;
43}
44
45struct TypedHandler<E, H> {
46 handler: Arc<H>,
47 _marker: PhantomData<E>,
48}
49
50impl<E, H> ErasedHandler for TypedHandler<E, H>
51where
52 E: Clone + Send + Sync + 'static,
53 H: EventHandler<E>,
54{
55 fn handle_erased(&self, event: &dyn Any) -> BoxFuture<'_, Result<()>> {
56 let event = match event.downcast_ref::<E>() {
57 Some(event) => event.clone(),
58 None => {
59 return Box::pin(async {
60 Err(crate::exception::startup_error("event type mismatch"))
61 });
62 }
63 };
64 let handler = self.handler.clone();
65
66 Box::pin(async move { handler.handle(event).await })
67 }
68}
69
70struct EventChannel<E> {
71 tx: broadcast::Sender<E>,
72}
73
74pub struct EventBus {
75 handlers: RwLock<HashMap<TypeId, Vec<Arc<dyn ErasedHandler>>>>,
76 broadcasts: RwLock<HashMap<TypeId, Box<dyn Any + Send + Sync>>>,
77}
78
79impl EventBus {
80 pub fn new() -> Self {
81 Self {
82 handlers: RwLock::new(HashMap::new()),
83 broadcasts: RwLock::new(HashMap::new()),
84 }
85 }
86
87 pub fn register<E, H>(&self, handler: Arc<H>) -> Result<()>
88 where
89 E: Clone + Send + Sync + 'static,
90 H: EventHandler<E>,
91 {
92 let wrapped = Arc::new(TypedHandler::<E, H> {
93 handler,
94 _marker: PhantomData,
95 });
96
97 self.handlers
98 .write()
99 .map_err(|_| crate::exception::startup_error("event handler registry lock poisoned"))?
100 .entry(TypeId::of::<E>())
101 .or_default()
102 .push(wrapped);
103 Ok(())
104 }
105
106 fn ensure_sender<E>(&self) -> Result<broadcast::Sender<E>>
108 where
109 E: Clone + Send + Sync + 'static,
110 {
111 let type_id = TypeId::of::<E>();
112
113 {
114 let broadcasts = self.broadcasts.read().map_err(|_| {
115 crate::exception::startup_error("event broadcast registry lock poisoned")
116 })?;
117 if let Some(channel) = broadcasts.get(&type_id) {
118 return channel
119 .downcast_ref::<EventChannel<E>>()
120 .ok_or_else(|| crate::exception::startup_error("event broadcast type mismatch"))
121 .map(|channel| channel.tx.clone());
122 }
123 }
124
125 let mut broadcasts = self.broadcasts.write().map_err(|_| {
126 crate::exception::startup_error("event broadcast registry lock poisoned")
127 })?;
128 let channel = broadcasts.entry(type_id).or_insert_with(|| {
129 let (tx, _rx) = broadcast::channel::<E>(EVENT_BROADCAST_CAPACITY);
130 Box::new(EventChannel { tx })
131 });
132
133 channel
134 .downcast_ref::<EventChannel<E>>()
135 .ok_or_else(|| crate::exception::startup_error("event broadcast type mismatch"))
136 .map(|channel| channel.tx.clone())
137 }
138
139 fn existing_sender<E>(&self) -> Result<Option<broadcast::Sender<E>>>
141 where
142 E: Clone + Send + Sync + 'static,
143 {
144 self.broadcasts
145 .read()
146 .map_err(|_| crate::exception::startup_error("event broadcast registry lock poisoned"))?
147 .get(&TypeId::of::<E>())
148 .map(|channel| {
149 channel
150 .downcast_ref::<EventChannel<E>>()
151 .ok_or_else(|| crate::exception::startup_error("event broadcast type mismatch"))
152 .map(|channel| channel.tx.clone())
153 })
154 .transpose()
155 }
156
157 pub fn subscribe<E>(&self) -> BoxStream<'static, Result<E>>
164 where
165 E: Clone + Send + Sync + 'static,
166 {
167 match self.ensure_sender::<E>() {
168 Ok(tx) => BroadcastStream::new(tx.subscribe())
169 .filter_map(|item| async move {
170 match item {
171 Ok(event) => Some(Ok(event)),
172 Err(BroadcastStreamRecvError::Lagged(_)) => {
173 tracing::warn!("event bus subscriber lagged; dropped events");
174 None
175 }
176 }
177 })
178 .boxed(),
179 Err(err) => stream::once(async move { Err(err) }).boxed(),
180 }
181 }
182
183 pub async fn emit<E>(&self, event: E) -> Result<()>
189 where
190 E: Clone + Send + Sync + 'static,
191 {
192 let handlers = self
193 .handlers
194 .read()
195 .map_err(|_| crate::exception::startup_error("event handler registry lock poisoned"))?
196 .get(&TypeId::of::<E>())
197 .cloned();
198
199 if let Some(handlers) = handlers {
200 for handler in handlers {
201 handler.handle_erased(&event).await?;
202 }
203 }
204
205 if let Some(tx) = self.existing_sender::<E>()? {
206 let _ = tx.send(event);
207 }
208
209 Ok(())
210 }
211
212 pub fn handler_count<E>(&self) -> Result<usize>
213 where
214 E: Clone + Send + Sync + 'static,
215 {
216 Ok(self
217 .handlers
218 .read()
219 .map_err(|_| crate::exception::startup_error("event handler registry lock poisoned"))?
220 .get(&TypeId::of::<E>())
221 .map_or(0, Vec::len))
222 }
223}
224
225impl Default for EventBus {
226 fn default() -> Self {
227 Self::new()
228 }
229}
230
231impl Injectable for EventBus {
232 fn dependencies() -> Vec<crate::ProviderDependency> {
233 crate::provider_dependencies![]
234 }
235
236 fn create(_container: &Container) -> BoxFuture<'_, Result<Self>> {
237 Box::pin(async { Ok(Self::new()) })
238 }
239}
240
241pub struct EventModule;
242
243impl Module for EventModule {
244 fn register() -> ModuleMetadata {
245 ModuleMetadata::new()
246 .provider::<EventBus>()
247 .export::<EventBus>()
248 }
249}
250
251pub struct EventHandlerDef {
252 type_id: TypeId,
253 type_name: &'static str,
254 register_fn: Box<dyn Fn(&Container) -> Result<()> + Send + Sync>,
255}
256
257impl EventHandlerDef {
258 pub(crate) fn of<H>() -> Self
259 where
260 H: RegisterableEventHandler + EventHandler<H::Event>,
261 {
262 Self {
263 type_id: TypeId::of::<H>(),
264 type_name: std::any::type_name::<H>(),
265 register_fn: Box::new(|container| {
266 let handler = container.resolve::<H>()?;
267 let bus = container.resolve::<EventBus>()?;
268 H::register_into(handler, &bus)
269 }),
270 }
271 }
272
273 pub(crate) fn for_event<E, H>() -> Self
274 where
275 E: Clone + Send + Sync + 'static,
276 H: Injectable + EventHandler<E>,
277 {
278 Self {
279 type_id: TypeId::of::<H>(),
280 type_name: std::any::type_name::<H>(),
281 register_fn: Box::new(|container| {
282 let handler = container.resolve::<H>()?;
283 let bus = container.resolve::<EventBus>()?;
284 bus.register::<E, H>(handler)
285 }),
286 }
287 }
288
289 pub(crate) fn assert_registered_or_declared(
290 &self,
291 declared: &std::collections::HashSet<TypeId>,
292 ) -> Result<()> {
293 if declared.contains(&self.type_id) {
294 return Ok(());
295 }
296
297 Err(crate::exception::startup_error(format!(
298 "missing event handler provider at startup: {} was declared by module metadata but was not registered as a provider",
299 self.type_name
300 )))
301 }
302
303 pub(crate) fn register(&self, container: &Container) -> Result<()> {
304 (self.register_fn)(container)
305 }
306}