Bsft.Outbox

The drain kernel every transactional outbox in a host shares: lease a batch, apply each row's side effect, mark what succeeded, hold back what failed and retire what keeps failing.

Install

dotnet add package Bsft.Outbox

Requires Bsft.Outbox.Abstractions (pulled transitively) and Bsft.Core. A store implementation comes from Bsft.Outbox.EFCore or from the host.

Register

services.AddBsftOutbox<MyPayload>("my-outbox", options =>
{
    options.BatchSize = 50;
});

The store and the side effect stay the owning package's to register: which rows this outbox holds and what they mean are the two things the kernel cannot guess. Run the drainer with Bsft.Core.Polling.PollLoop from a hosted service of your own, or drain on demand through IOutboxDrainer<TPayload>.

Configure

Every outbox is a named options instance, bound from Bsft:Outbox:Instances:<name> when the registration is handed an IConfiguration:

services.AddBsftOutbox<MyPayload>("my-outbox", builder.Configuration);
{ "Bsft": { "Outbox": { "Instances": { "my-outbox": { "BatchSize": 50 } } } } }

The action overload still applies, and when both are used the action runs after the section.

Option Default Effect
BsftOutboxOptions.PollInterval 00:00:05 How long a loop waits after a pass that found nothing. Must be positive.
BsftOutboxOptions.BatchSize 100 The most rows one pass claims. Must be at least 1.
BsftOutboxOptions.LeaseDuration 00:01:00 How long a claim holds. Must be positive, and has to cover a whole batch.
BsftOutboxOptions.MaxDeliveryAttempts 10 How often a row may fail before it is retired. Must be at least 1.
BsftOutboxOptions.RetryBackoff 00:00:05 The first interval a failed row waits; doubles per attempt. Must not be negative.
BsftOutboxOptions.MaxRetryDelay 00:05:00 The ceiling of the schedule and the clamp on what a failure may ask for. Must be positive.

Validation: the host is refused at start, naming the outbox, the option and the value it was given. The drainer's constructor asks the same rules again, for a caller that builds one without the options pipeline.

Extend

IOutboxSideEffect<TPayload> (what a row means, applied before the row is marked; there is no default — the owning package writes one). IOutboxStore<TPayload> (where the rows live; Bsft.Outbox.EFCore implements the lease protocol once). IOutboxRetrySchedule (how long a failed row waits; the shipped one is exponential with jitter and honours IRetryAfter as a floor).

Documentation

Topic page: docs/outbox.md. Conventions: docs/package-conventions.md.