Skip to main content

ironflow_engine/notify/
subscriber.rs

1//! [`EventSubscriber`] trait -- react to domain events.
2
3use std::future::Future;
4use std::pin::Pin;
5
6use super::Event;
7
8/// Boxed future returned by [`EventSubscriber::handle`].
9pub type SubscriberFuture<'a> = Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
10
11/// A subscriber that reacts to domain events.
12///
13/// Implement this trait to create custom notification channels (Slack,
14/// Discord, PagerDuty, etc.). The engine broadcasts events to all
15/// registered subscribers via [`EventPublisher`](super::EventPublisher).
16///
17/// # Contract
18///
19/// - [`handle`](EventSubscriber::handle) is called only for events that
20///   match the filter configured at subscription time.
21/// - Implementations must not block -- heavy work should be spawned.
22/// - Errors are logged internally; they must not propagate.
23///
24/// # Examples
25///
26/// ```no_run
27/// use ironflow_engine::notify::{EventSubscriber, Event, SubscriberFuture};
28///
29/// struct LogSubscriber;
30///
31/// impl EventSubscriber for LogSubscriber {
32///     fn name(&self) -> &str { "log" }
33///
34///     fn handle<'a>(&'a self, event: &'a Event) -> SubscriberFuture<'a> {
35///         Box::pin(async move {
36///             println!("[{}] {:?}", event.event_type(), event);
37///         })
38///     }
39/// }
40/// ```
41pub trait EventSubscriber: Send + Sync {
42    /// A short identifier for this subscriber (used in logs).
43    fn name(&self) -> &str;
44
45    /// Handle a domain event.
46    ///
47    /// Only called for events matching the filter set at subscription
48    /// time. The subscriber does not need to filter.
49    fn handle<'a>(&'a self, event: &'a Event) -> SubscriberFuture<'a>;
50}