DcsvIo.D2.Caching.Distributed.Redis 0.1.2

dotnet add package DcsvIo.D2.Caching.Distributed.Redis --version 0.1.2
                    
NuGet\Install-Package DcsvIo.D2.Caching.Distributed.Redis -Version 0.1.2
                    
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="DcsvIo.D2.Caching.Distributed.Redis" Version="0.1.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DcsvIo.D2.Caching.Distributed.Redis" Version="0.1.2" />
                    
Directory.Packages.props
<PackageReference Include="DcsvIo.D2.Caching.Distributed.Redis" />
                    
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 DcsvIo.D2.Caching.Distributed.Redis --version 0.1.2
                    
#r "nuget: DcsvIo.D2.Caching.Distributed.Redis, 0.1.2"
                    
#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 DcsvIo.D2.Caching.Distributed.Redis@0.1.2
                    
#: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=DcsvIo.D2.Caching.Distributed.Redis&version=0.1.2
                    
Install as a Cake Addin
#tool nuget:?package=DcsvIo.D2.Caching.Distributed.Redis&version=0.1.2
                    
Install as a Cake Tool

DcsvIo.D2.Caching.Distributed.Redis

Redis-backed implementation of IDistributedCache and ICacheInvalidationBackplane. Wraps StackExchange.Redis.

Install

dotnet add package DcsvIo.D2.Caching.Distributed.Redis

Public surface

RedisDistributedCache : IDistributedCache — implements every building block (ICacheBasic + ICacheAtomic + ICacheBroadcast + ICacheSet) over a StackExchange.Redis.IConnectionMultiplexer.

RedisCacheInvalidationBackplane : ICacheInvalidationBackplane — pub/sub-backed invalidation channel. Subscribes once at construction; dispatches to all registered handlers per the universal "everyone acts" rule.

JsonCacheSerializer : ICacheSerializer — default value serializer. System.Text.Json, dev-friendly (Redis CLI can inspect values directly). Pluggable via ICacheSerializer registration.

RedisCacheOptions — connection string, default TTL, key prefix, channel name, command/connect timeouts, retries.

services.AddD2DistributedCacheRedis(opts => …) — registers RedisDistributedCache + the underlying IConnectionMultiplexer.

services.AddD2RedisCacheInvalidationBackplane() — opt-in registration of the pub/sub backplane. Required for *AndBroadcast* methods on the cache (and on tiered caches that compose it).

Lua scripts (internal)

Three Lua scripts live in RedisLuaScripts.cs. They make compound atomic ops into single round-trips:

  • INCREMENT_WITH_OPTIONAL_TTLINCRBY + conditional PEXPIRE. Used by IncrementAsync. Sets the TTL only when explicitly requested; existing TTLs survive subsequent increments.
  • RELEASE_LOCK_IF_OWNER — compare-and-delete. ReleaseLockAsync only DELs if the stored value matches the caller's lockId. Defeats the ABA pattern where someone else's lock would otherwise be released by a stale releaser.
  • SET_ADD_WITH_OPTIONAL_TTLSADD + conditional PEXPIRE on first add. Sets TTL only when the set is being created; existing sets keep their TTL.

Lua is intentionally NOT exposed as a public surface (IRedisScriptExecutor etc.). If a future caller genuinely needs custom scripts, they can take a private dep on this lib and add what they need internally — keeping Lua as an implementation detail of the Redis impl preserves portability if we ever swap to a different backing store.

Error handling

  • Connection lost / timeout (RedisException)D2Result.ServiceUnavailable (graceful degradation; caller decides fail-open vs fail-closed via Result inspection).
  • WRONGTYPE on Increment (key holds a non-string data structure) — D2Result.Conflict.
  • "value is not an integer or out of range" on Increment (key holds a non-numeric string) — D2Result.Conflict.
  • Serialization failureD2Result with error code COULD_NOT_BE_SERIALIZED / COULD_NOT_BE_DESERIALIZED.

Connection management

AddD2DistributedCacheRedis(opts) registers IConnectionMultiplexer as a singleton — one connection pool shared across the app. The connection is built from RedisCacheOptions.ConnectionString (StackExchange format: host:port[,host:port],password=...,ssl=true). Sentinel and Cluster topologies are inferred from the connection string.

Defaults that matter:

  • AbortOnConnectFail = false — graceful degradation if Redis isn't up at startup; cache calls return ServiceUnavailable until it comes back.
  • CommandTimeout = 2s, ConnectTimeout = 5s, ConnectRetries = 3 — tuneable per RedisCacheOptions.

Observability

Static Meter (DcsvIo.D2.Caching.Distributed.Redis) emits aggregate counters: d2.cache.redis.{hits, misses, sets, removes, broadcasts, errors}. No per-call spans — Redis ops are network-bound (1-5ms) and a per-call ActivitySource span would dominate at typical cache rates without adding signal worth the noise. The aggregate counters are what tells you "is the cache healthy" (hit rate, error rate); per-call observability is reserved for the consuming handler's own pipeline.

Test coverage

Integration/Caching/Distributed/ (xunit collection "Redis", shared Testcontainers Redis fixture):

  • RedisDistributedCacheTests — full op surface against real Redis. Includes:
    • SetNxAsync_Concurrent_OnlyOneWinsAcrossCluster — 32 contenders, exactly one wins (cluster-wide atomic SET NX)
    • IncrementAsync_Concurrent_AggregatesAtomically — 8×200 increments aggregate to exactly 1600 (cluster-wide atomic INCR via Lua)
    • IncrementAsync_OnNonNumeric_ReturnsConflict — Redis WRONGTYPE / "not an integer" → Conflict (verifies both paths)
    • SetAddAsync_Concurrent_BuildsCorrectCardinality — 100 concurrent SADDs with 30 distinct values → SCARD = 30
    • AcquireReleaseLock_RoundTrip + ReleaseLockAsync_WrongOwner_DoesNotRelease — Lua compare-and-delete defeats ABA
  • RedisCacheInvalidationBackplaneTests — pub/sub backplane against real Redis. Verifies:
    • Universal "everyone acts" rule (publisher receives own messages)
    • Multi-subscriber independence (each gets every message)
    • Error isolation (one throwing handler doesn't break others)
    • Disposal stops handler invocation
    • Cross-instance delivery (publish on instance A → received on instance B)

The test container is launched once per test run via Testcontainers.Redis and shared across all [Collection("Redis")] test classes. Each test uses a fresh key prefix / channel name for isolation.

Dependencies

  • DcsvIo.D2.Caching.AbstractionsIDistributedCache, ICacheInvalidationBackplane, ICacheSerializer
  • StackExchange.Redis — Redis client
  • Microsoft.Extensions.Options, Microsoft.Extensions.DependencyInjection.Abstractions, Microsoft.Extensions.Logging.Abstractions

References

  • DcsvIo.D2.Caching.Abstractions — interface + result-mapping reference
  • DcsvIo.D2.Caching.Tiered — composes Local + this lib for L1+L2 cascades
  • Product Edge rate-limit middleware is the primary consumer of ICacheSet for FP-too-common detection (product surface; out of scope for this library README).
Product Compatible and additional computed target framework versions.
.NET 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 (1)

Showing the top 1 NuGet packages that depend on DcsvIo.D2.Caching.Distributed.Redis:

Package Downloads
DcsvIo.D2.Telemetry

OpenTelemetry SDK setup for D2 — traces, metrics, logs, OTLP exporters, an IP-restricted Prometheus endpoint, and aggregation of every shared library's ActivitySource and Meter.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.2 107 7/17/2026
0.1.1 104 7/17/2026