1use crate::{
4 app::{App, AppBuilder},
5 config::env::Env,
6 error::Result,
7 plugin::ComponentRegistry,
8};
9use async_trait::async_trait;
10use dashmap::DashMap;
11use std::{
12 any::{Any, TypeId},
13 future::Future,
14 net::SocketAddr,
15 path::PathBuf,
16 sync::Arc,
17};
18
19#[async_trait]
21pub trait BuilderEventListener: Send + Sync {
22 async fn on_event(
24 &self,
25 event: Arc<dyn Any + Send + Sync>,
26 app: &mut AppBuilder,
27 ) -> Result<()>;
28}
29
30struct TypedBuilderListener<E, F> {
31 listener: F,
32 _marker: std::marker::PhantomData<fn(E)>,
33}
34
35#[async_trait]
36impl<E, F, Fut> BuilderEventListener for TypedBuilderListener<E, F>
37where
38 E: Event,
39 F: Fn(E, &mut AppBuilder) -> Fut + Send + Sync,
40 Fut: Future<Output = Result<()>> + Send,
41{
42 async fn on_event(
43 &self,
44 event: Arc<dyn Any + Send + Sync>,
45 app: &mut AppBuilder,
46 ) -> Result<()> {
47 let event = event
48 .downcast::<E>()
49 .expect("event listener received unexpected event type");
50 (self.listener)((*event).clone(), app).await
51 }
52}
53
54type BuilderListener = Arc<dyn BuilderEventListener>;
55
56#[async_trait]
58pub trait AppEventListener: Send + Sync {
59 async fn on_event(&self, event: Arc<dyn Any + Send + Sync>, app: &App) -> Result<()>;
61}
62
63struct TypedAppListener<E, F> {
64 listener: F,
65 _marker: std::marker::PhantomData<fn(E)>,
66}
67
68#[async_trait]
69impl<E, F, Fut> AppEventListener for TypedAppListener<E, F>
70where
71 E: Event,
72 F: Fn(E, &App) -> Fut + Send + Sync,
73 Fut: Future<Output = Result<()>> + Send,
74{
75 async fn on_event(&self, event: Arc<dyn Any + Send + Sync>, app: &App) -> Result<()> {
76 let event = event
77 .downcast::<E>()
78 .expect("event listener received unexpected event type");
79 (self.listener)((*event).clone(), app).await
80 }
81}
82
83type AppListener = Arc<dyn AppEventListener>;
84
85pub trait Event: Clone + Send + Sync + 'static {}
87
88#[derive(Clone, Default)]
90pub struct EventBus {
91 builder_listeners: Arc<DashMap<TypeId, Vec<BuilderListener>>>,
92 app_listeners: Arc<DashMap<TypeId, Vec<AppListener>>>,
93}
94
95impl EventBus {
96 pub fn listen_dyn<E>(&self, listener: BuilderListener)
98 where
99 E: Event,
100 {
101 self.builder_listeners
102 .entry(TypeId::of::<E>())
103 .or_default()
104 .push(listener);
105 }
106
107 pub fn listen_app_dyn<E>(&self, listener: AppListener)
109 where
110 E: Event,
111 {
112 self.app_listeners
113 .entry(TypeId::of::<E>())
114 .or_default()
115 .push(listener);
116 }
117
118 pub fn listen<E, F, Fut>(&self, listener: F)
120 where
121 E: Event,
122 F: Fn(E, &mut AppBuilder) -> Fut + Send + Sync + 'static,
123 Fut: Future<Output = Result<()>> + Send,
124 {
125 self.builder_listeners
126 .entry(TypeId::of::<E>())
127 .or_default()
128 .push(Arc::new(TypedBuilderListener {
129 listener,
130 _marker: std::marker::PhantomData,
131 }));
132 }
133
134 pub fn listen_app<E, F, Fut>(&self, listener: F)
136 where
137 E: Event,
138 F: Fn(E, &App) -> Fut + Send + Sync + 'static,
139 Fut: Future<Output = Result<()>> + Send,
140 {
141 self.app_listeners
142 .entry(TypeId::of::<E>())
143 .or_default()
144 .push(Arc::new(TypedAppListener {
145 listener,
146 _marker: std::marker::PhantomData,
147 }));
148 }
149
150 pub async fn publish_builder<E>(&self, event: E, app: &mut AppBuilder) -> Result<()>
152 where
153 E: Event,
154 {
155 let listeners = self
156 .builder_listeners
157 .get(&TypeId::of::<E>())
158 .map(|entry| entry.clone())
159 .unwrap_or_default();
160
161 let event = Arc::new(event) as Arc<dyn Any + Send + Sync>;
162 for listener in listeners {
163 listener.on_event(event.clone(), app).await?;
164 }
165
166 Ok(())
167 }
168
169 pub async fn publish_app<E>(&self, event: E, app: &App) -> Result<()>
171 where
172 E: Event,
173 {
174 let listeners = self
175 .app_listeners
176 .get(&TypeId::of::<E>())
177 .map(|entry| entry.clone())
178 .unwrap_or_default();
179
180 let event = Arc::new(event) as Arc<dyn Any + Send + Sync>;
181 for listener in listeners {
182 listener.on_event(event.clone(), app).await?;
183 }
184
185 Ok(())
186 }
187}
188
189#[async_trait]
191pub trait BuilderEventPublisher {
192 async fn publish<E>(&mut self, event: E) -> Result<()>
194 where
195 E: Event;
196}
197
198#[async_trait]
200pub trait EventPublisher: Sync {
201 async fn publish<E>(&self, event: E) -> Result<()>
203 where
204 E: Event;
205}
206
207pub trait EventSubscriber {
209 fn listen_dyn<E>(&self, listener: Arc<dyn BuilderEventListener>)
211 where
212 E: Event;
213
214 fn listen<E, F, Fut>(&self, listener: F)
216 where
217 E: Event,
218 F: Fn(E, &mut AppBuilder) -> Fut + Send + Sync + 'static,
219 Fut: Future<Output = Result<()>> + Send;
220}
221
222pub trait AppEventSubscriber {
224 fn listen_app_dyn<E>(&self, listener: Arc<dyn AppEventListener>)
226 where
227 E: Event;
228
229 fn listen_app<E, F, Fut>(&self, listener: F)
231 where
232 E: Event,
233 F: Fn(E, &App) -> Fut + Send + Sync + 'static,
234 Fut: Future<Output = Result<()>> + Send;
235}
236
237#[async_trait]
238impl BuilderEventPublisher for AppBuilder {
239 async fn publish<E>(&mut self, event: E) -> Result<()>
240 where
241 E: Event,
242 {
243 let bus = self.get_expect_component::<EventBus>().clone();
244 bus.publish_builder(event, self).await
245 }
246}
247
248#[async_trait]
249impl EventPublisher for App {
250 async fn publish<E>(&self, event: E) -> Result<()>
251 where
252 E: Event,
253 {
254 self.get_expect_component::<EventBus>()
255 .publish_app(event, self)
256 .await
257 }
258}
259
260impl EventSubscriber for AppBuilder {
261 fn listen_dyn<E>(&self, listener: Arc<dyn BuilderEventListener>)
262 where
263 E: Event,
264 {
265 self.get_expect_component::<EventBus>()
266 .listen_dyn::<E>(listener);
267 }
268
269 fn listen<E, F, Fut>(&self, listener: F)
270 where
271 E: Event,
272 F: Fn(E, &mut AppBuilder) -> Fut + Send + Sync + 'static,
273 Fut: Future<Output = Result<()>> + Send,
274 {
275 self.get_expect_component::<EventBus>().listen(listener);
276 }
277}
278
279impl AppEventSubscriber for AppBuilder {
280 fn listen_app_dyn<E>(&self, listener: Arc<dyn AppEventListener>)
281 where
282 E: Event,
283 {
284 self.get_expect_component::<EventBus>()
285 .listen_app_dyn::<E>(listener);
286 }
287
288 fn listen_app<E, F, Fut>(&self, listener: F)
289 where
290 E: Event,
291 F: Fn(E, &App) -> Fut + Send + Sync + 'static,
292 Fut: Future<Output = Result<()>> + Send,
293 {
294 self.get_expect_component::<EventBus>().listen_app(listener);
295 }
296}
297
298impl AppEventSubscriber for App {
299 fn listen_app_dyn<E>(&self, listener: Arc<dyn AppEventListener>)
300 where
301 E: Event,
302 {
303 self.get_expect_component::<EventBus>()
304 .listen_app_dyn::<E>(listener);
305 }
306
307 fn listen_app<E, F, Fut>(&self, listener: F)
308 where
309 E: Event,
310 F: Fn(E, &App) -> Fut + Send + Sync + 'static,
311 Fut: Future<Output = Result<()>> + Send,
312 {
313 self.get_expect_component::<EventBus>().listen_app(listener);
314 }
315}
316
317#[derive(Debug, Clone, PartialEq, Eq)]
319pub enum ConfigSource {
320 File(PathBuf),
322 Inline,
324}
325
326#[derive(Debug, Clone)]
328pub struct ConfigEvent {
329 pub env: Env,
331 pub source: ConfigSource,
333}
334
335impl Event for ConfigEvent {}
336
337#[derive(Debug, Clone)]
339pub struct PluginsBuiltEvent;
340
341impl Event for PluginsBuiltEvent {}
342
343#[derive(Debug, Clone)]
345pub struct ServicesInjectedEvent;
346
347impl Event for ServicesInjectedEvent {}
348
349#[derive(Clone)]
351pub struct AppBuiltEvent {
352 pub app: Arc<App>,
354}
355
356impl Event for AppBuiltEvent {}
357
358#[derive(Debug, Clone, Copy, PartialEq, Eq)]
360pub enum ShutdownPhase {
361 BeforeHooks,
363 AfterHooks,
365}
366
367#[derive(Debug, Clone)]
369pub struct ShutdownEvent {
370 pub phase: ShutdownPhase,
372}
373
374impl Event for ShutdownEvent {}
375
376#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
378pub enum ServerProtocol {
379 Http,
381 Grpc,
383}
384
385impl ServerProtocol {
386 pub fn as_str(self) -> &'static str {
388 match self {
389 Self::Http => "http",
390 Self::Grpc => "grpc",
391 }
392 }
393}
394
395#[derive(Debug, Clone)]
401pub struct ServerStartedEvent {
402 pub addr: SocketAddr,
404 pub protocol: ServerProtocol,
406}
407
408impl Event for ServerStartedEvent {}
409
410#[cfg(test)]
411mod tests {
412 use super::{BuilderEventPublisher, Event, EventSubscriber};
413 use crate::app::AppBuilder;
414 use crate::error::Result;
415 use std::sync::{
416 atomic::{AtomicUsize, Ordering},
417 Arc,
418 };
419 use tokio::sync::Mutex;
420
421 #[derive(Clone)]
422 struct TestEvent(usize);
423
424 impl Event for TestEvent {}
425
426 #[derive(Clone)]
427 struct OtherEvent;
428
429 impl Event for OtherEvent {}
430
431 #[tokio::test]
432 async fn publish_dispatches_to_matching_listeners() -> Result<()> {
433 let mut app = AppBuilder::default();
434 let total = Arc::new(AtomicUsize::new(0));
435 let total_ref = total.clone();
436
437 app.listen(move |event: TestEvent, _app: &mut AppBuilder| {
438 let total = total_ref.clone();
439 async move {
440 total.fetch_add(event.0, Ordering::SeqCst);
441 Ok(())
442 }
443 });
444
445 app.publish(TestEvent(3)).await?;
446 assert_eq!(total.load(Ordering::SeqCst), 3);
447 Ok(())
448 }
449
450 #[tokio::test]
451 async fn publish_keeps_event_types_isolated() -> Result<()> {
452 let mut app = AppBuilder::default();
453 let total = Arc::new(AtomicUsize::new(0));
454 let total_ref = total.clone();
455
456 app.listen(move |_: TestEvent, _app: &mut AppBuilder| {
457 let total = total_ref.clone();
458 async move {
459 total.fetch_add(1, Ordering::SeqCst);
460 Ok(())
461 }
462 });
463
464 app.publish(OtherEvent).await?;
465 assert_eq!(total.load(Ordering::SeqCst), 0);
466 Ok(())
467 }
468
469 #[tokio::test]
470 async fn publish_dispatches_listeners_in_registration_order() -> Result<()> {
471 let mut app = AppBuilder::default();
472 let calls = Arc::new(Mutex::new(Vec::new()));
473
474 let first = calls.clone();
475 app.listen(move |_: TestEvent, _app: &mut AppBuilder| {
476 let calls = first.clone();
477 async move {
478 calls.lock().await.push(1);
479 Ok(())
480 }
481 });
482
483 let second = calls.clone();
484 app.listen(move |_: TestEvent, _app: &mut AppBuilder| {
485 let calls = second.clone();
486 async move {
487 calls.lock().await.push(2);
488 Ok(())
489 }
490 });
491
492 app.publish(TestEvent(0)).await?;
493 assert_eq!(*calls.lock().await, vec![1, 2]);
494 Ok(())
495 }
496}