Expand description
Domain event bus — typed pub-sub for application-level events
decoupled from the ORM. Use this for cross-component fanout
(OrderPlaced → mail + billing + audit handlers); use
signals for per-Model lifecycle hooks. See events::EventBus.
Domain event bus — typed pub-sub for application-level events
decoupled from the ORM. Closes future-backlog item #45 (“internal
event bus / domain event dispatch decoupled from ORM signals”).
§When to use this vs crate::signals
signals— per-Modellifecycle hooks (pre/post save, pre/post delete). Tied to ORM write paths. Use when you need “every time row X changes, do Y.”events— arbitrary application events not tied to a specific Model. Use when you need “publish that an order was placed and let mail / billing / audit each react in their own subscriber.” Decouples cross-component fanout.
Same shape (typed, async, multi-subscriber, sequential dispatch); different intent.
§Quick start
ⓘ
use rustango::events::EventBus;
use std::sync::Arc;
#[derive(Clone)]
struct OrderPlaced { order_id: i64, total_cents: i64 }
let bus = EventBus::new();
// Subscribe (anywhere — main, app init, a service constructor):
bus.subscribe::<OrderPlaced, _>(|e| Box::pin(async move {
println!("billing: charging {} cents for order {}", e.total_cents, e.order_id);
})).await;
// Publish (from a handler, a job, a worker):
bus.publish(OrderPlaced { order_id: 42, total_cents: 9999 }).await;§Semantics
- Subscribers run sequentially, in subscription order, awaited
one at a time. (For parallel fanout, wrap a subscriber body in
tokio::spawn.) - The event is
Cloned once per subscriber so each receives an owned value.E: Clone + Send + Sync + 'staticis required. - A panicking subscriber aborts the dispatch chain and propagates
to the caller of
publish. Usetokio::spawnfor isolation if that’s a concern. - The bus is cheap to clone — internal state is
Arc-shared. Pass clones into axum State, services, etc.
Structs§
- Event
Bus - In-process domain event bus. Cheap to clone — internal state is
Arc-shared. - Subscriber
Id - Opaque identifier returned by
EventBus::subscribefor later use withEventBus::unsubscribe.
Type Aliases§
- Handler
Future - Future returned by event handlers.
'staticbecause the handler is stored asArc<dyn ...>and may run after the caller returns.