Skip to main content

Module events

Module events 

Source
Expand description

Domain event bus — typed pub-sub for application events, separate from the ORM. Use it for cross-component fan-out (OrderPlaced → mail + billing + audit). For per-model lifecycle hooks use signals instead. See events::EventBus. Domain event bus: typed pub-sub for application events, separate from the ORM.

§This or crate::signals?

  • signals hook a Model lifecycle (pre/post save, pre/post delete). Use them for “whenever row X changes, do Y”.
  • events are not tied to a model. Use them for “an order was placed”, where mail, billing and audit each react on their own.

Both are typed, async, multi-subscriber and dispatch in order.

§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 one at a time, in subscription order. For parallel fan-out, tokio::spawn inside the subscriber.
  • The event is cloned once per subscriber, so E must be Clone + Send + Sync + 'static.
  • A panicking subscriber is logged and skipped; the rest still run and publish returns normally.
  • The bus is cheap to clone; state is shared. Pass clones into axum state or your services.

Structs§

EventBus
In-process domain event bus. Cheap to clone; clones share state.
SubscriberId
Opaque identifier returned by EventBus::subscribe for later use with EventBus::unsubscribe.

Type Aliases§

HandlerFuture
Future returned by event handlers. 'static because the handler is stored as Arc<dyn ...> and may run after the caller returns.