Transactional outbox: publish an event as part of a database transaction.
publish-in-tx! writes the event to event_outbox on the caller's open
transaction, so it commits or rolls back with the business change. A relay
polls the table, publishes each pending row to the bus in order, and marks
it delivered. A relay that dies between publish and mark publishes the row
again: delivery is at-least-once, and consumers dedupe on :id (BOU-448).
Relays on several replicas take turns through a lease row in
event_outbox_relay, so one publishes at a time and order holds. The lease
is timed by the database clock, so replica clock skew cannot split it.
A row that fails :max-attempts times over :dead-letter-after-ms, or
cannot be decoded, is dead-lettered and skipped so later events still flow;
after a failed pass the relay backs off (BOU-679). dead-letters lists
them and requeue! puts them back.
Times are epoch-millis BIGINTs and ids text, so the same SQL runs on H2, PostgreSQL, MySQL and SQLite without per-engine encoding.
Transactional outbox: publish an event as part of a database transaction. `publish-in-tx!` writes the event to `event_outbox` on the caller's open transaction, so it commits or rolls back with the business change. A relay polls the table, publishes each pending row to the bus in order, and marks it delivered. A relay that dies between publish and mark publishes the row again: delivery is at-least-once, and consumers dedupe on `:id` (BOU-448). Relays on several replicas take turns through a lease row in `event_outbox_relay`, so one publishes at a time and order holds. The lease is timed by the database clock, so replica clock skew cannot split it. A row that fails `:max-attempts` times over `:dead-letter-after-ms`, or cannot be decoded, is dead-lettered and skipped so later events still flow; after a failed pass the relay backs off (BOU-679). `dead-letters` lists them and `requeue!` puts them back. Times are epoch-millis BIGINTs and ids text, so the same SQL runs on H2, PostgreSQL, MySQL and SQLite without per-engine encoding.
(create-outbox ds bus & [opts])An outbox over datasource ds that relays to bus. opts as defaults.
An outbox over datasource `ds` that relays to `bus`. `opts` as `defaults`.
(create-outbox-table! ds)Create event_outbox, its index and the relay lease row if absent. Called
at boot by the :wagoe/events-outbox component.
Create `event_outbox`, its index and the relay lease row if absent. Called at boot by the `:wagoe/events-outbox` component.
(dead-letters {:keys [ds]})Dead-lettered rows, oldest first: :id, :topic, :attempts,
:last-error, :dead-ms.
Dead-lettered rows, oldest first: `:id`, `:topic`, `:attempts`, `:last-error`, `:dead-ms`.
(relay-once! outbox)Publish up to :batch-size pending rows in order and mark them delivered.
Stops at the first failed publish, so a later event never overtakes an
earlier one; the failed row is retried next pass. A row dead-lettered
instead (see record-failure!) is skipped and the pass goes on. Does
nothing while another relay holds the lease. Returns the count delivered.
Publish up to `:batch-size` pending rows in order and mark them delivered. Stops at the first failed publish, so a later event never overtakes an earlier one; the failed row is retried next pass. A row dead-lettered instead (see `record-failure!`) is skipped and the pass goes on. Does nothing while another relay holds the lease. Returns the count delivered.
(requeue! {:keys [ds]} ids)Make dead-lettered rows ids pending again, failures forgotten. They
keep their place, so the relay publishes them before anything newer still
pending. Returns the count requeued.
Make dead-lettered rows `ids` pending again, failures forgotten. They keep their place, so the relay publishes them before anything newer still pending. Returns the count requeued.
(start-relay! outbox)Poll every :poll-ms, backing off after a failed pass. Returns outbox
with its :executor.
Poll every `:poll-ms`, backing off after a failed pass. Returns `outbox` with its `:executor`.
(stop-relay! {:keys [owner lease] :as outbox})Stop polling and hand the lease to the next relay. Rows not yet relayed stay pending.
Stop polling and hand the lease to the next relay. Rows not yet relayed stay pending.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |