backbone_messaging/noop.rs
1//! No-op event publisher implementations.
2//!
3//! Use these in tests and simple contexts where event publishing
4//! is wired but should produce no side effects.
5
6use async_trait::async_trait;
7use std::marker::PhantomData;
8
9use crate::error::EventError;
10
11/// A no-op implementation of any event publishing contract.
12///
13/// Accepts any event type, discards it silently, and returns `Ok(())`.
14/// Use this as the default publisher in generated services so that
15/// `Option<Publisher>` is never needed.
16///
17/// # Example
18///
19/// ```rust,ignore
20/// use backbone_messaging::NoOpPublisher;
21///
22/// let publisher: NoOpPublisher<MyEvent> = NoOpPublisher::new();
23/// publisher.publish(my_event).await?; // does nothing
24/// ```
25pub struct NoOpPublisher<E> {
26 _phantom: PhantomData<E>,
27}
28
29impl<E> NoOpPublisher<E> {
30 pub fn new() -> Self {
31 Self {
32 _phantom: PhantomData,
33 }
34 }
35}
36
37impl<E> Default for NoOpPublisher<E> {
38 fn default() -> Self {
39 Self::new()
40 }
41}
42
43/// Synchronous publish trait — the minimal contract for a publisher.
44/// Both real and no-op publishers implement this.
45#[async_trait]
46pub trait Publisher<E: Send + Sync + 'static>: Send + Sync {
47 async fn publish(&self, event: E) -> Result<(), EventError>;
48
49 async fn publish_many(&self, events: Vec<E>) -> Result<(), EventError> {
50 for event in events {
51 self.publish(event).await?;
52 }
53 Ok(())
54 }
55}
56
57#[async_trait]
58impl<E: Send + Sync + 'static> Publisher<E> for NoOpPublisher<E> {
59 async fn publish(&self, _event: E) -> Result<(), EventError> {
60 Ok(())
61 }
62
63 async fn publish_many(&self, _events: Vec<E>) -> Result<(), EventError> {
64 Ok(())
65 }
66}
67
68// ─── NoOpEventBus ─────────────────────────────────────────────────────────────
69
70/// A non-generic, type-erased no-op event bus.
71///
72/// Unlike `NoOpPublisher<E>`, this single struct can publish **any** event type
73/// without being parameterized. Use it in contexts where a concrete bus
74/// instance is required but no event forwarding is desired.
75///
76/// This eliminates the `Option<event_bus>` anti-pattern in services — a service
77/// can always hold an `Arc<NoOpEventBus>` and call `publish()` unconditionally.
78///
79/// # Example
80///
81/// ```rust,ignore
82/// use backbone_messaging::NoOpEventBus;
83///
84/// let bus = NoOpEventBus::new();
85/// bus.publish(my_event).await?; // silently discarded
86/// ```
87pub struct NoOpEventBus;
88
89impl NoOpEventBus {
90 pub fn new() -> Self {
91 Self
92 }
93
94 /// Publish any event — always succeeds, does nothing.
95 pub async fn publish<E: Send + 'static>(&self, _event: E) -> Result<(), EventError> {
96 Ok(())
97 }
98}
99
100impl Default for NoOpEventBus {
101 fn default() -> Self {
102 Self::new()
103 }
104}