Skip to main content

FusionCache

Respire.FusionCache provides an IFusionCacheBackplane for FusionCache 2.9.0 or later compatible releases. Respire.Caching supplies its IDistributedCache L2. Both adapters can share the same caller-owned IRespireClient.

dotnet add package Respire.FusionCache
dotnet add package Respire.Caching
dotnet add package ZiggyCreatures.FusionCache.Serialization.SystemTextJson

Shared-client setup​

using Microsoft.Extensions.DependencyInjection;
using Respire.Caching;
using Respire.FusionCache;
using ZiggyCreatures.Caching.Fusion;
using ZiggyCreatures.Caching.Fusion.Serialization.SystemTextJson;

await using var client = await RespireClient.ConnectAsync("redis://localhost");
var services = new ServiceCollection();
services.AddSingleton<IRespireClient>(client);
services.AddRespireDistributedCache(options => options.InstanceName = "myapp:cache:");
services.AddFusionCache()
.WithOptions(options =>
{
options.BackplaneChannelPrefix = "myapp:cache";
options.WaitForInitialBackplaneSubscribe = true;
})
.WithSerializer(new FusionCacheSystemTextJsonSerializer())
.WithRegisteredDistributedCache()
.WithRespireBackplane();

await using var provider = services.BuildServiceProvider();
var cache = provider.GetRequiredService<IFusionCache>();
await cache.SetAsync("product:42", 42);

The service provider disposes the cache and its backplane before the caller disposes client. Neither adapter disposes that externally supplied client. The backplane uses Respire's shared subscription infrastructure; it does not create another command client. The serializer above is supplied by FusionCache. Configure its serialization separately from Respire's serializer, including any application-specific AOT requirements.

For direct construction, pass a RespireFusionCacheBackplane to FusionCache's SetupBackplane. For registered-service discovery, call AddFusionCacheRespireBackplane and FusionCache's WithRegisteredBackplane. The registration is transient: each cache needs a separate backplane instance, even when the client is shared. WithRespireBackplane also creates a separate instance for each cache.

Channels and compatibility​

The adapter uses regular SUBSCRIBE/PUBLISH with the literal channel name selected by FusionCache. It uses FusionCache's public BackplaneMessage serialization and interoperates with ZiggyCreatures.FusionCache.Backplane.StackExchangeRedis 2.9.0. It does not opt into sharded pub/sub. RESP2 and RESP3 are supported through the client's existing subscription infrastructure.

Give communicating nodes the same cache name, channel prefix, L2 key prefix, and serializer. Use distinct names/prefixes for unrelated applications. Redis pub/sub is not scoped to a database, and Respire's WithKeyPrefix does not prefix these channels. A database number or L2 key prefix alone therefore does not isolate backplane traffic.

Delivery gaps and lifecycle​

Respire reconnects and resubscribes automatically. The adapter consumes its ordered gap markers outside the receive path, logs reconnect or buffer-overflow gaps, and invokes FusionCache's connection handler with IsReconnection = true. Initial subscription reports false. FusionCache applies its own recovery policy; Redis pub/sub cannot replay messages lost during an outage or local overflow. The backplane does not promise durable delivery or a database snapshot. The core pub/sub metrics continue to record these gaps.

Optional RespireSubscriptionOptions on the constructor and registration methods control buffer size and overflow policy. Unspecified values inherit the client settings. Callbacks run in order on a background consumer. Slow callbacks can fill the bounded buffer; malformed messages and callback exceptions are logged without preventing later valid messages. Synchronous and asynchronous subscription entry points use their corresponding FusionCache callbacks, with the other callback form as a fallback when only that form is supplied.

Await successful unsubscribe before reusing an instance. Subscribing an active or still retiring instance fails. A callback that unsubscribes itself must return before that instance can be subscribed again. Unsubscribe and disposal stop its transport subscription and join in-progress callbacks; a callback that unsubscribes itself does not wait for itself. Disposal cannot interrupt arbitrary application callback code, so callbacks must finish for external teardown to complete. Concurrent teardown callers join the same work. Disposing the shared client or exhausting its reconnect policy ends the subscription; publishing on that ended subscription fails explicitly. Publishing before subscription or after disposal also fails.

A terminal subscription end is logged, rather than reported as a reconnect notification. It does not clear the instance's subscription state automatically. To reuse the backplane, await UnsubscribeAsync (or call Unsubscribe), then call SubscribeAsync (or Subscribe) again once the shared client can connect. If the caller has disposed that client or its pub/sub reconnect policy has been exhausted, create a replacement client and a new backplane instance instead. Exhaustion permanently rejects new subscriptions on that client, even if Redis becomes available again.

Cancellation passed to publishing reaches Respire. As with other network writes, cancellation after submission does not prove that Redis did not accept the notification. In-flight publishes may complete while teardown starts.

The distributed locker is tracked separately in #1114. This package's backplane does not yet implement that contract.