The outbox the deliveries are kept in; wrap it once (see the class).
Where the fence is kept; a durable one carries it across a restart.
Adds a pending delivery as the wrapped outbox does. Behind the fence it is stored content-free instead, as
bot:purged with an empty payload, and the run's content is scrubbed again, so a fence another process wrote reaches
this outbox's rows too.
Claims one delivery under the run's guard and sends it once the guard is released, so no enqueue or claim for the
run waits for its destination. Under the guard, behind the fence, the run's content is scrubbed first; then the
delivery is read again (a purge may have emptied it since due returned it) and, while it is still pending and no
other send of it is under way here, send gets the fresh row and a signal that a purge of the run aborts. True when
send resolved; false when the delivery is gone, no longer pending or being sent already, or a purge cancelled the
send; rejects with send's own error otherwise.
A delivery due returned.
Sends the fresh copy; it stops at the signal before it writes the body.
Fences the run's deliveries and empties its content deliveries in the wrapped outbox, delivered ones included. The run's sends under way here are aborted at once, before the fence's write, and again once the fence is written; the purge then waits for them to end before it scrubs, so when it resolves no send of the run's content is still in progress in this process. A send must therefore never wait for a purge of its own run.
The wrapped outbox's pending deliveries due at now.
Optional limit: numberEvery delivery of the run in the wrapped outbox.
Optional Readonly forgetPresent when the wrapped outbox has forget: forgets the run's deliveries there, and its fence here and in the
DeliveryFence when that forgets too. Call it only after the run's producers have stopped.
Wraps an IOutbox so that a purge of a run reaches its deliveries in flight, not only its stored rows.
purgeContentaborts the run's sends under way before it writes the fence, waits for them to end, then empties the run's content deliveries in the wrapped outbox, delivered ones included.sendClaimedclaims one delivery under the run's guard: behind the fence it scrubs the run's content first, then reads the delivery again, so a purge that landed while the dispatcher resolved its destination sends the content-freebot:purgedbody in its place. The send itself goes out once the guard is released.bot:purgedwith an empty payload, whatever its type (bot:doneincluded): its destination learns only the delivery's ids and the run's.Wrap each outbox once per process and give that one wrapper to the manager and to the
OutboxDispatcher: a second wrapper of the same outbox does not see the first one's sends, so a purge through one cannot cancel a send through the other. A run's enqueues, claims, scrubs andforgetrun one at a time, and a send runs outside that guard: an enqueue for a run, and with it the manager's handling of the run's events (a participant's stop among them), never waits for a destination; only a purge waits for the run's sends, once it has cancelled them. A delivery is sent once at a time here: a pass that takes a delivery another pass is still sending skips it. Over an outbox that evicts whole runs (an in-memory one) the wrapper hasforgettoo, which forgets the run's fence with its deliveries, so the manager's eviction after the retention grace goes on as it does without the wrapper.