RedisEventOutbox Class
The outbox on Redis's own structures: a list carries each stream's order, a hash carries the items, and every mutation is a server-side operation - append, remove-by-value, field delete - so concurrent transmitter REPLICAS compose instead of overwriting each other, which is the hole a whole-queue-as-one-value implementation cannot close.
public sealed class RedisEventOutbox : Abblix.SharedSignals.Transmitter.IEventOutboxInheritance System.Object → RedisEventOutbox
Implements IEventOutbox
Remarks
The mutations run as server-side scripts rather than MULTI/EXEC, and the difference is what the caller is told. Redis has no rollback in either form: a command that fails at execution time does not undo its predecessors. But a transaction reports that failure only inside the EXEC reply, which a caller discarding the per-command tasks never reads - so a half-applied enqueue returned success, and the signed event sat in the hash unreachable forever. A script's error reaches the caller instead. What remains possible is a partial write, so the order is chosen to make the survivor harmless: the payload is stored first and listed second, because a payload nobody listed is invisible and expires, while a listing whose payload never arrived would be served forever and never acknowledged.
The queue and item keys of one stream share a cluster hash tag, so they land on one slot and the multi-key scripts here stay valid under Redis Cluster.
Losing Redis loses pending events, and the tier is deliberate. SSF 1.0 Section 8.1.2.1 lets a transmitter drop events it holds while a stream is PAUSED; for an enabled stream the same section requires transmission, so treating the whole queue as cache-tier is our decision rather than a permission the specification grants. It follows the delivery protocols' own tolerance for redelivery and loss over a broken transport, and it is why the queue belongs beside caches rather than beside data that earns backups.
Constructors
RedisEventOutbox(IConnectionMultiplexer, RedisOutboxOptions) Constructor
The outbox on Redis's own structures: a list carries each stream's order, a hash carries the items, and every mutation is a server-side operation - append, remove-by-value, field delete - so concurrent transmitter REPLICAS compose instead of overwriting each other, which is the hole a whole-queue-as-one-value implementation cannot close.
public RedisEventOutbox(StackExchange.Redis.IConnectionMultiplexer connection, Abblix.SharedSignals.Redis.RedisOutboxOptions options);Parameters
connection StackExchange.Redis.IConnectionMultiplexer
The Redis connection; opening and configuring it is the host's.
options RedisOutboxOptions
What the queue may keep, and for how long.
Remarks
The mutations run as server-side scripts rather than MULTI/EXEC, and the difference is what the caller is told. Redis has no rollback in either form: a command that fails at execution time does not undo its predecessors. But a transaction reports that failure only inside the EXEC reply, which a caller discarding the per-command tasks never reads - so a half-applied enqueue returned success, and the signed event sat in the hash unreachable forever. A script's error reaches the caller instead. What remains possible is a partial write, so the order is chosen to make the survivor harmless: the payload is stored first and listed second, because a payload nobody listed is invisible and expires, while a listing whose payload never arrived would be served forever and never acknowledged.
The queue and item keys of one stream share a cluster hash tag, so they land on one slot and the multi-key scripts here stay valid under Redis Cluster.
Losing Redis loses pending events, and the tier is deliberate. SSF 1.0 Section 8.1.2.1 lets a transmitter drop events it holds while a stream is PAUSED; for an enabled stream the same section requires transmission, so treating the whole queue as cache-tier is our decision rather than a permission the specification grants. It follows the delivery protocols' own tolerance for redelivery and loss over a broken transport, and it is why the queue belongs beside caches rather than beside data that earns backups.
Methods
RedisEventOutbox.AcknowledgeAsync(string, string, IReadOnlyCollection<string>, CancellationToken) Method
Removes acknowledged SETs from a stream's queue, releasing the transmitter from retaining them (RFC 8936 Section 2.2). Identifiers with nothing to match are ignored - an acknowledgement can only arrive for something that was once here.
public System.Threading.Tasks.Task AcknowledgeAsync(string receiverId, string streamId, System.Collections.Generic.IReadOnlyCollection<string> jwtIds, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));Parameters
receiverId System.String
The receiver the stream belongs to.
streamId System.String
The stream whose queue is acknowledged.
jwtIds System.Collections.Generic.IReadOnlyCollection<System.String>
The "jti" values being acknowledged.
cancellationToken System.Threading.CancellationToken
Cancels I/O a durable implementation performs.
Implements AcknowledgeAsync(string, string, IReadOnlyCollection<string>, CancellationToken)
Returns
RedisEventOutbox.ClearAsync(string, string, CancellationToken) Method
Drops a stream's whole queue - the companion of deleting or disabling the stream, whose events are not held for later (SSF 1.0 Sections 8.1.1.5, 8.1.2.1).
public System.Threading.Tasks.Task ClearAsync(string receiverId, string streamId, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));Parameters
receiverId System.String
The receiver the stream belongs to.
streamId System.String
The stream whose queue is dropped.
cancellationToken System.Threading.CancellationToken
Cancels I/O a durable implementation performs.
Implements ClearAsync(string, string, CancellationToken)
Returns
RedisEventOutbox.EnqueueAsync(string, string, OutboxItem, CancellationToken) Method
Appends a SET to a stream's queue.
public System.Threading.Tasks.Task EnqueueAsync(string receiverId, string streamId, Abblix.SharedSignals.Transmitter.OutboxItem item, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));Parameters
receiverId System.String
The receiver the stream belongs to.
streamId System.String
The stream the SET was minted for.
item OutboxItem
The minted SET.
cancellationToken System.Threading.CancellationToken
Cancels I/O a durable implementation performs.
Implements EnqueueAsync(string, string, OutboxItem, CancellationToken)
Returns
RedisEventOutbox.PendingAsync(string, string, Nullable<int>, CancellationToken) Method
Reads the unacknowledged head of a stream's queue, oldest first, without removing anything - redelivery of the unacknowledged is the delivery protocols' own semantics.
public System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Abblix.SharedSignals.Transmitter.OutboxItem>> PendingAsync(string receiverId, string streamId, System.Nullable<int> maxCount=null, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));Parameters
receiverId System.String
The receiver the stream belongs to.
streamId System.String
The stream whose queue is read.
maxCount System.Nullable<System.Int32>
The most items to return; null returns everything pending, mirroring an absent "maxEvents" (RFC 8936 Section 2.2).
cancellationToken System.Threading.CancellationToken
Cancels I/O a durable implementation performs.
Implements PendingAsync(string, string, Nullable<int>, CancellationToken)
Returns
System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<OutboxItem>>