Skip to content

RedisDeliveryLease Class

The delivery lease across instances, on the one Redis primitive that can express it: a write conditional on the key not existing, carrying its own expiry. Every transmitter instance asks the same server, so exactly one of them is told yes.

C#
public sealed class RedisDeliveryLease : Abblix.SharedSignals.Transmitter.IDeliveryLease

Inheritance System.Object → RedisDeliveryLease

Implements IDeliveryLease

Remarks

This is why the lease is not offered over IDistributedCache. That interface writes whole values unconditionally - it has no set-if-absent - so a lease built on it would be taken by every instance that asked, and a lock everyone holds is worse than none: the sweep would look coordinated while behaving exactly as it does with no lease at all.

Releasing compares before deleting, and the case it exists for is the ordinary one rather than an exotic race: a holder whose pass ran past the deadline no longer owns the name, another instance has taken it, and an unconditional delete would hand the name to a third while the second was still working. The comparison and the delete are one script because reading and then deleting is that same defect with a smaller window.

One key per name, so the script is single-key and needs no cluster hash tag to stay valid under Redis Cluster.

Constructors

RedisDeliveryLease(IConnectionMultiplexer) Constructor

The delivery lease across instances, on the one Redis primitive that can express it: a write conditional on the key not existing, carrying its own expiry. Every transmitter instance asks the same server, so exactly one of them is told yes.

C#
public RedisDeliveryLease(StackExchange.Redis.IConnectionMultiplexer connection);

Parameters

connection StackExchange.Redis.IConnectionMultiplexer

The Redis connection; opening and configuring it is the host's.

Remarks

This is why the lease is not offered over IDistributedCache. That interface writes whole values unconditionally - it has no set-if-absent - so a lease built on it would be taken by every instance that asked, and a lock everyone holds is worse than none: the sweep would look coordinated while behaving exactly as it does with no lease at all.

Releasing compares before deleting, and the case it exists for is the ordinary one rather than an exotic race: a holder whose pass ran past the deadline no longer owns the name, another instance has taken it, and an unconditional delete would hand the name to a third while the second was still working. The comparison and the delete are one script because reading and then deleting is that same defect with a smaller window.

One key per name, so the script is single-key and needs no cluster hash tag to stay valid under Redis Cluster.

Methods

RedisDeliveryLease.TryAcquireAsync(string, TimeSpan, CancellationToken) Method

Claims name for at most duration.

C#
public System.Threading.Tasks.Task<System.IAsyncDisposable?> TryAcquireAsync(string name, System.TimeSpan duration, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));

Parameters

name System.String

What is being claimed. Callers scope it themselves, so two kinds of work over one stream do not collide.

duration System.TimeSpan

How long the claim holds without being released. It bounds two opposite costs: too short cuts a legitimate pass off and the work is redone next time, too long parks the work for the remainder after the holder dies. Both are safe, so err on whichever the deployment minds less.

cancellationToken System.Threading.CancellationToken

Cancels the I/O a shared implementation performs.

Implements TryAcquireAsync(string, TimeSpan, CancellationToken)

Returns

System.Threading.Tasks.Task<System.IAsyncDisposable>
A handle that releases the claim when disposed, or null when someone else holds it - which is an ordinary outcome and not a failure. Releasing is conditional on still holding it, so a handle disposed after its deadline cannot revoke the claim of whoever took over.