outbox

Generated by tinox doc

tinox.core.outbox: transactional outbox over tinox.core.db and AMQP 0-9-1 publisher confirms.

ModuleVersionGroup
db1.2.2tinox.core
amqp0911.3.0tinox.core

class Outbox

* Writing side of the transactional outbox. add() stores the message in table `tinox_outbox` with * the ORM, i.e. on the connection of the caller's @Transactional method: the message is committed * or rolled back together with the business data, never separately. Nothing is sent here.

Methods

fnc add(destination: String, messageId: String, payload: String) → Nothing
* @param destination queue name (routing key on the default exchange) * @param messageId stable key of this logical message (the consumer deduplicates on it); must be * non-empty and at most 255 bytes * @param payload the message body as text (encode structured data yourself, e.g. JSON)
fnc backlog() → Int64
Records not yet confirmed by the broker and not parked
fnc parked() → Int64
Records parked after maxAttempts failures: they need an operator (fix the cause, set status back to 0)
fnc lagMs() → Int64
Age in ms of the oldest pending record, 0 if there is none (how far the dispatcher lags behind)

class OutboxDispatcher

* Publishing side of the outbox: reads pending records (oldest first, 50 per batch), publishes each to * its queue with the record's messageId as AMQP message-id using publisher confirms, and marks it sent * only after the broker confirmed it. * * Delivery is AT-LEAST-ONCE. If the process dies after the broker confirmed but before the record is * marked sent (or the confirm is lost), the record is published again after a restart, with the same * messageId: consumers must deduplicate on it (IdempotencyWindow091 or a unique key in their database). * No committed record is lost: a record stays pending until a confirm was seen. Failures are retried with * exponential backoff (backoffMs * 2^attempts, capped at 60 s) and parked after maxAttempts, so nothing * retries forever. Order is by id, but a record in backoff is overtaken by later ones.

Fields

hostString
portInt64
vhostString
userString
passString
maxAttemptsInt64
backoffMsInt64
confirmTimeoutMsInt64
connsList<AmqpConnection091>
chansList<AmqpChannel091>
connectedBool
stopRequestedBool
confirmedInt64
failuresInt64

Methods

fnc create(host: String, port: Int64, vhost: String, user: String, pass: String, maxAttempts: Int64, backoffMs: Int64) → OutboxDispatcher
fn connect() → Bool
Opens the connection and enables publisher confirms; false (and nothing open) on failure
fn close() → Nothing
fn runOnce() → Int64
Publishes one batch; returns how many records the broker confirmed
fn publishOne(rec: OutboxRecord) → Bool
Publish + wait for the confirm of one record; settles the record either way
fn run(pollMs: Int64) → Nothing
* Runs until stop() (or until the owning task scope is cancelled), draining the current batch * before it returns; sleeps pollMs between empty rounds. Always closes the connection.
fn stop() → Nothing

@Entity@Tableclass OutboxRecord

* One message waiting to be published. Written by Outbox::add inside the application's own * transaction, published (and marked sent) later by the OutboxDispatcher. * * Table `tinox_outbox`; create it in your changelog, see docs/outbox.md. * status: 0 pending, 1 sent (broker confirmed), 2 parked (maxAttempts failed -- needs an operator).

Fields

@Id@GeneratedValueidInt64
@ColumndestinationString
@ColumnmessageIdString
@ColumnpayloadString
@ColumnstatusInt64
@ColumnattemptsInt64
@ColumnlastErrorString
@ColumncreatedAtInt64
@ColumnnextAttemptAtInt64
@ColumnsentAtInt64