Skip to main content

Module outbox

Module outbox 

Source
Expand description

Outbox pattern for reliable at-least-once outbound message delivery.

§Why the outbox?

When a process transition generates an outbound EDIFACT message (e.g. an APERAK acknowledgement), two writes must happen atomically:

  1. Domain events are appended to the event store.
  2. The EDIFACT payload is queued for delivery to the AS4 endpoint.

Without the outbox, a crash between steps 1 and 2 silently loses the outbound message. With the outbox, both writes are part of the same database transaction — a background delivery worker then delivers pending messages, surviving crashes and transient AS4 failures transparently.

§Usage

// After a command dispatch that should trigger an outbound APERAK:
let env = &aperak_envelopes[0];
let msg = OutboxMessage::new(
    process.stream_id().clone(),
    env.process_id,
    env.tenant_id,
    env.correlation_id,
    env.conversation_id,
    env.event_id,
    "APERAK",
    &recipient_gln,
    aperak_payload_json,
);
outbox_store.enqueue(&[msg]).await?;

// Background delivery worker:
let pending = outbox_store.pending_now(50).await?;
for msg in pending {
    as4_client.send(&msg).await?;
    outbox_store.acknowledge(msg.message_id).await?;
}

§Atomicity contract

[InMemoryOutboxStore] does not guarantee transactional atomicity with InMemoryEventStore. Persistent backend crates (mako-event-store-slatedb, mako-event-store-postgres) MUST enqueue messages in the same database transaction as the event append.

Structs§

NoopOutboxStore
An OutboxStore that silently discards all messages.
OutboxMessage
An outbound message queued for delivery via AS4 or another channel.
PendingOutbox
A lightweight outbox message specification produced by Workflow::handle.

Traits§

OutboxStore
Storage contract for outbox messages.

Functions§

outbox_idempotency_key
Compute a deterministic idempotency key for an outbound message.