Innovabit.DotNet.Interceptors.Coordination.Abstractions 2.0.117

dotnet add package Innovabit.DotNet.Interceptors.Coordination.Abstractions --version 2.0.117
                    
NuGet\Install-Package Innovabit.DotNet.Interceptors.Coordination.Abstractions -Version 2.0.117
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Innovabit.DotNet.Interceptors.Coordination.Abstractions" Version="2.0.117" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Innovabit.DotNet.Interceptors.Coordination.Abstractions" Version="2.0.117" />
                    
Directory.Packages.props
<PackageReference Include="Innovabit.DotNet.Interceptors.Coordination.Abstractions" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Innovabit.DotNet.Interceptors.Coordination.Abstractions --version 2.0.117
                    
#r "nuget: Innovabit.DotNet.Interceptors.Coordination.Abstractions, 2.0.117"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Innovabit.DotNet.Interceptors.Coordination.Abstractions@2.0.117
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Innovabit.DotNet.Interceptors.Coordination.Abstractions&version=2.0.117
                    
Install as a Cake Addin
#tool nuget:?package=Innovabit.DotNet.Interceptors.Coordination.Abstractions&version=2.0.117
                    
Install as a Cake Tool

Innovabit.DotNet.Interceptors.Coordination.Abstractions

Three answers to "this must not happen twice" for Innovabit.DotNet.Interceptors, in one package because they share one question — which calls are the same call? Pick a provider for the two that need somewhere to keep state:

  • Innovabit.DotNet.Interceptors.Coordination.Memory — in this process.
  • Innovabit.DotNet.Interceptors.Coordination.Redis — shared across instances.

Which one do you want

Stops Use it when
[Idempotent] The same side effect happening twice A client retries a charge, a broker redelivers a message
[SingleFlight] The same work running twice at once, in this process A hot cache entry expires and a hundred callers all miss
[DistributedLock] The same work running twice at once, anywhere A nightly job must not run in two instances; a per-aggregate write must be serialised

They compose: [SingleFlight] collapses the local stampede, [DistributedLock] serialises what is left across instances, [Idempotent] makes the whole thing safe to retry.

Usage

services
    .AddInterceptors()
    .AddRedisCoordination();          // or .AddInMemoryCoordination()

services.AddScopedWithInterception<IPaymentService, PaymentService>();
public class PaymentService : IPaymentService
{
    // Runs once per idempotency key; a replay gets the original receipt back.
    [Idempotent(KeyFrom = nameof(idempotencyKey))]
    public Task<Receipt> ChargeAsync(string idempotencyKey, Order order) { ... }

    // One run per tenant at a time, across every instance.
    [DistributedLock(KeyFrom = nameof(tenantId), LeaseSeconds = 300)]
    public Task RebuildAsync(string tenantId) { ... }

    // A hundred simultaneous misses become one call.
    [SingleFlight(KeyFrom = nameof(symbol))]
    [Cache(DurationSeconds = 30)]
    public Task<Quote> QuoteAsync(string symbol) { ... }
}

[Idempotent]

Property Meaning
KeyFrom Required. Parameter holding the key — a client's Idempotency-Key, a message id.
Name Namespace for the key. Share it between methods the same request may arrive through.
RetentionSeconds How long a result is remembered. Defaults to 86400 (one day).

KeyFrom is required on purpose: an idempotency key identifies the request, and there is nothing in a method signature a library could safely invent one from. Omitting it throws.

A result is only remembered once the call succeeds. A failure leaves no trace and the next attempt runs normally — retrying a failure has to be allowed, which is the other half of retrying a success being free.

Retention is how long you are protected for: a retry arriving after it runs again. Match it to how long the caller might keep retrying, not to the smallest number that seems to work.

This is not caching. A cache is an optimisation you could switch off; this is a guarantee about a side effect happening once, which is why it runs outside both the cache and the transaction.

[SingleFlight]

A cache stops repeated work after the first call finishes. It does nothing about the callers that all miss at the same instant — exactly what happens when a hot entry expires. [SingleFlight] makes them share one call.

Coalescing is per process: sharing an in-flight call across a network is not something a lock can do, so behind four instances a stampede of four remains. That is the difference between a manageable spike and an outage.

A failure is shared too — everyone waiting on the one call that ran sees its exception — and is never remembered: the next call starts fresh. Synchronous methods pass straight through, since a thread that is blocked has nothing to join.

[DistributedLock]

Property Meaning
KeyFrom Parameter that scopes the lock, so two aggregates do not queue behind each other.
Name Name the lock is held under.
WaitSeconds How long to wait before giving up. Defaults to 0 — fail rather than queue.
LeaseSeconds How long the lock survives unreleased. Defaults to 30.

A caller that cannot take the lock in time gets DistributedLockNotAcquiredException and never reaches the method.

The lease is also the limit of the promise. It exists so a holder that dies does not block everyone forever, which means a method that outlives its lease loses the lock while still running and two copies can overlap. No lease-based lock avoids this. Size the lease above the method's worst case, and treat the lock as protection against the common case rather than a guarantee of mutual exclusion under arbitrary pauses.

Ordering

… Idempotency 180 → Caching 200 → SingleFlight 250 → DistributedLock 270 → … Retry 500 … Transaction 700
  • Idempotency outside caching, so a replay answers without even a cache lookup, and outside the transaction, so a result is only remembered once the work it describes has committed.
  • SingleFlight inside caching, because what it collapses is concurrent cache misses, and outside the lock, because coalescing locally is free and taking a remote lock is not.
  • DistributedLock inside caching so a cache hit takes no lock, and outside retry and transaction so one holder owns the whole unit of work, attempts included.

Keys

All three resolve a key the same way: the operation's Name (or Type.Method), optionally narrowed by the value of the KeyFrom parameter. Values are rendered with the invariant culture, so the same request cannot resolve to two keys depending on the thread that served it. A KeyFrom matching no parameter throws and names the parameters that do exist — silently widening the scope is the kind of mistake that only shows up once it is already doing the wrong thing.

License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on Innovabit.DotNet.Interceptors.Coordination.Abstractions:

Package Downloads
Innovabit.DotNet.Interceptors.All

Meta-package: every interceptor concern in the suite (logging, validation, caching, notifications, telemetry, audit, authorization, rate limiting, coordination, feature gates, transactions, retry/timeout/circuit breaker/fallback) in one reference. Providers are separate packages — pick the ones you use.

Innovabit.DotNet.Interceptors.Coordination.Redis

Redis idempotency and distributed lock stores for interceptor-based coordination.

Innovabit.DotNet.Interceptors.Coordination.Memory

In-process idempotency and lock stores for interceptor-based coordination.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.117 0 10/31/2026
2.0.116 130 10/26/2026
2.0.115 144 10/17/2026
2.0.114 134 10/10/2026
2.0.113 150 10/3/2026
2.0.112 154 9/28/2026
2.0.111 144 9/28/2026
2.0.110 146 9/27/2026
2.0.109 149 9/26/2026
2.0.108 148 9/26/2026
2.0.107 150 9/26/2026
2.0.106 151 9/25/2026
2.0.105 141 9/25/2026
1.0.0.104 131 9/25/2026
1.0.0.103 133 9/25/2026