Expand description
Transactional-outbox drainer runtime.
Entities declared with #[entity(events(outbox))] enqueue their
lifecycle events into the entity_outbox table inside the same
transaction as the write. This module delivers those rows:
ⓘ
use entity_core::outbox::{OutboxDrainer, OutboxHandler, OutboxRow};
struct Notifier;
#[async_trait::async_trait]
impl OutboxHandler for Notifier {
type Error = anyhow::Error;
async fn handle(&self, row: &OutboxRow) -> Result<(), Self::Error> {
send_somewhere(&row.entity, &row.payload).await
}
}
OutboxDrainer::new(pool, Notifier)
.run() // polls until the task is aborted
.await;§Delivery Semantics
- Rows are claimed with
FOR UPDATE SKIP LOCKED, so multiple drainers cooperate without double delivery. - A successful
handlemarks the row processed; a failure schedules a retry with exponential backoff (base_backoff * 2^attempts). - After
max_attemptsfailures the row stays unprocessed withnext_attempt_atin the far future — inspect and repair manually. - At-least-once delivery: handlers must be idempotent.
Structs§
- Outbox
Drainer - Polling drainer delivering
entity_outboxrows to a handler. - Outbox
Row - One claimed outbox row handed to the
OutboxHandler.
Enums§
- Outbox
Action - Outcome of handling one claimed outbox row.
Traits§
- Outbox
Handler - User-provided delivery target for outbox rows.
Functions§
- backoff_
delay - Compute the retry delay for a row that has already failed
attemptstimes. - process_
rows - Run the handler over claimed rows and decide per-row follow-up.