Class OutboxServiceCollectionExtensions
- Namespace
- Microsoft.Extensions.DependencyInjection
- Assembly
- Stratara.Outbox.RabbitMQ.dll
Service-collection extensions for the Stratara outbox + projection-replay stack.
public static class OutboxServiceCollectionExtensions
- Inheritance
-
OutboxServiceCollectionExtensions
- Inherited Members
Methods
AddOutboxDispatcher(IServiceCollection)
Registers ICommandOutboxDispatcher and IEventBundleOutboxDispatcher (scoped) and, transitively, IProjectionReplayState (singleton via AddProjectionReplayState(IServiceCollection)).
public static IServiceCollection AddOutboxDispatcher(this IServiceCollection services)
Parameters
servicesIServiceCollection
Returns
Examples
builder.AddMessaging();
builder.Services.AddOutboxDispatcher();
Remarks
The transitive IProjectionReplayState registration is intentional: the outbox dispatchers
consult it before each publish to skip the fast-path while a projection replay is in progress. The
underlying registration uses TryAddSingleton, so it is safe to call this method together with
AddProjectionReplayState(IServiceCollection) or AddEventProjectionWorkerServices() — duplicates collapse.
AddOutboxWorker(IServiceCollection, IConfiguration)
Registers the Stratara.Outbox.RabbitMQ.Outbox.OutboxWorker hosted service and binds OutboxOptions from configuration.
public static IServiceCollection AddOutboxWorker(this IServiceCollection services, IConfiguration configuration)
Parameters
servicesIServiceCollectionconfigurationIConfiguration
Returns
Examples
Binds OutboxOptions from the Outbox section. A cycle takes one batch of each kind,
so BatchSize and PollingIntervalSeconds together set the drain rate:
// appsettings.json: { "Outbox": { "BatchSize": 10000, "PollingIntervalSeconds": 30 } }
services.AddOutboxWorker(configuration);
Remarks
Each polling cycle is guarded by IOutboxLock. The default registration is Stratara.Outbox.RabbitMQ.Outbox.NullOutboxLock, a no-op that always grants the lock — safe only for single-instance deployments. For multi-replica setups call AddRedisOutboxLock(IServiceCollection) afterwards, which overrides the no-op with a Redis-leased lock that lets only one replica drain at a time.
AddProjectionReplayState(IServiceCollection)
Registers the singleton IProjectionReplayState: Redis-backed where an
StackExchange.Redis.IConnectionMultiplexer is registered, held in process otherwise. Idempotent
(TryAddSingleton).
public static IServiceCollection AddProjectionReplayState(this IServiceCollection services)
Parameters
servicesIServiceCollection
Returns
Examples
One host needs no Redis; a deployment whose replay must reach several hosts registers the shared connection, in either order:
// appsettings.json: { "ProjectionReplay": { "LeaseSeconds": 600 } }
services.AddProjectionReplayState();
builder.AddCaching(); // optional: makes the replay state span hosts
Remarks
The choice is made when the state is first resolved, not when this method runs, so the order
of AddCaching() and the composites does not matter. With a Redis connection the replay
marking, its progress and the replay-request channel are shared by every host on that
connection, and a replay requested in one suppresses publication in all of them. Whether a
replay is active is answered from the host's memory either way — no dispatch, publication or
catch-up waits on Redis for it — and a marking that changed in another host is seen within
RefreshSeconds at the latest, usually at once. Without a
Redis connection the state lives in this process only — a replay requested here suppresses
publication here only — and the host records that once at start-up as a warning (event
104_012). A host that registers its own IProjectionReplayState keeps it.
Also registers ProjectionReplayOptions, read from the ProjectionReplay
section of the IConfiguration the container holds, so the replay marking is leased even
when the consumer configures nothing. A service collection that holds no configuration gets the
defaults. A value configured in code with services.Configure<ProjectionReplayOptions>(...)
after this call takes precedence over the section; one configured before it is overwritten for
every key the section carries. The section is applied once, at the position of the first call,
so calling this method again — directly, through AddOutboxDispatcher(IServiceCollection) or through a
composite — does not re-apply it.
A LeaseSeconds of zero or less is refused when the host
starts, with an OptionsValidationException naming
ProjectionReplay:LeaseSeconds; so is a RefreshSeconds
of zero or less, or at or above the lease, naming ProjectionReplay:RefreshSeconds.
AddRedisOutboxLock(IServiceCollection)
Replaces the default Stratara.Outbox.RabbitMQ.Outbox.NullOutboxLock with the Redis-backed Stratara.Outbox.RabbitMQ.Outbox.RedisOutboxLock, enabling safe multi-instance outbox-worker deployments.
public static IServiceCollection AddRedisOutboxLock(this IServiceCollection services)
Parameters
servicesIServiceCollection
Returns
Examples
Required before running more than one outbox-worker replica; the default lock is a no-op that
assumes a single instance. Needs an IConnectionMultiplexer, which AddCaching()
registers:
builder.AddCaching();
builder.Services.AddRedisOutboxLock();
Remarks
Requires StackExchange.Redis.IConnectionMultiplexer to be registered (for
example via AddCaching() from Stratara.Infrastructure). The lock is leased
with LockLeaseSeconds; tune the lease to comfortably exceed the
worst-case drain duration.