Skip to main content

rust_webx_core/mediator/
default.rs

1//! IMediator implementation.
2//!
3//! `Mediator::send` delegates to the shared [`dispatch`](super::dispatch::dispatch)
4//! function — the same path used by HTTP endpoint adapters after request construction.
5//!
6//! `Mediator::publish` resolves `IEventHandler<T>` from the DI container and
7//! invokes all registered handlers.
8
9use std::sync::Arc;
10
11use rust_dix::ScopeFactory;
12
13use super::dispatch;
14use super::{IEventRequest, IMediator, IRequest};
15use crate::error::Result;
16use crate::handler::IEventHandler;
17
18/// Default implementation of IMediator.
19///
20/// Holds a reference to the root `ServiceProvider`. Each `send` call creates
21/// a per-request scope so Scoped services (e.g. DbContext) are resolved fresh.
22pub struct Mediator {
23    provider: Arc<rust_dix::ServiceProvider>,
24}
25
26impl Mediator {
27    pub fn new(provider: Arc<rust_dix::ServiceProvider>) -> Self {
28        Self { provider }
29    }
30}
31
32#[async_trait::async_trait]
33impl IMediator for Mediator {
34    async fn send<T, R>(&self, req: T) -> Result<R>
35    where
36        T: IRequest<R> + Send + 'static,
37        R: serde::Serialize + Send + 'static,
38    {
39        dispatch::dispatch(&self.provider, req).await
40    }
41
42    async fn publish<T: IEventRequest>(&self, event: T) -> Result<()> {
43        let scope = self.provider.create_scope();
44        let handlers: Vec<Arc<dyn IEventHandler<T>>> = scope.get_all::<dyn IEventHandler<T>>();
45
46        let mut first_err: Option<crate::error::Error> = None;
47        for handler in handlers {
48            if let Err(e) = handler.handle(event.clone()).await {
49                if first_err.is_none() {
50                    first_err = Some(e);
51                }
52            }
53        }
54
55        match first_err {
56            Some(e) => Err(e),
57            None => Ok(()),
58        }
59    }
60}