< Summary - AsyncResponse (Release / net8.0+net10.0 / unit+integration)

Information
Class: Microsoft.Extensions.DependencyInjection.RedisAsyncResponseServiceCollectionExtensions
Assembly: AsyncResponse.Channels.Redis
File(s): /_/src/Channels/AsyncResponse.Channels.Redis/ServiceCollectionExtensions.cs
Line coverage
100%
Covered lines: 31
Uncovered lines: 0
Coverable lines: 31
Total lines: 80
Line coverage: 100%
Branch coverage
75%
Covered branches: 3
Total branches: 4
Branch coverage: 75%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
WithRedisChannel(...)75%44100%

File(s)

/_/src/Channels/AsyncResponse.Channels.Redis/ServiceCollectionExtensions.cs

#LineLine coverage
 1using AsyncResponse;
 2using AsyncResponse.Channels.Redis;
 3using Microsoft.Extensions.DependencyInjection.Extensions;
 4using Microsoft.Extensions.Options;
 5
 6namespace Microsoft.Extensions.DependencyInjection;
 7
 8/// <summary>
 9/// DI registration for the Redis-backed AsyncResponse channel package.
 10/// </summary>
 11public static class RedisAsyncResponseServiceCollectionExtensions
 12{
 13    /// <summary>
 14    /// Registers Redis pub/sub as the response channel — behind <see cref="IAsyncResponsePublisher"/>,
 15    /// <see cref="IAsyncResponseSubscriber"/>, and <see cref="IRecoverableAsyncResponseSubscriber"/> —
 16    /// together with the durable Redis recovery-state store, so a response that arrives after the
 17    /// waiter died (e.g. a redeploy) can still resume or fail the owning flow. It also registers
 18    /// <see cref="IRecoverableAsyncResponseBuilder"/> for fluent durable recovery flows. The same
 19    /// channel instance serves the engine's recovery-state scanner and active-subscriber probe, so the
 20    /// watchdog works against Redis automatically.
 21    /// <para>
 22    /// Requires a <c>StackExchange.Redis.IConnectionMultiplexer</c> singleton registered by the
 23    /// host — reuse the application's existing multiplexer; don't create a second connection.
 24    /// Publisher/subscriber resolve to one shared instance: per-interface instances would split the
 25    /// channel's internal per-channel state.
 26    /// </para>
 27    /// </summary>
 28    public static AsyncResponseRegistrationBuilder WithRedisChannel(
 29        this AsyncResponseRegistrationBuilder builder,
 30        Action<RedisAsyncResponseOptions>? configure = null)
 31    {
 43832        var services = builder.Services;
 43833        services.AddOptions();
 43834        if (configure is not null)
 35        {
 37236            services.Configure(configure);
 37        }
 38
 39        // Durable recovery store; also the watchdog's recovery-state scanner.
 43840        services.TryAddSingleton<RedisRecoveryStateStore>();
 86541        services.Replace(ServiceDescriptor.Singleton<IRecoveryStateStore>(provider => provider.GetRequiredService<RedisR
 77342        services.Replace(ServiceDescriptor.Singleton<IRecoveryStateScanner>(provider => provider.GetRequiredService<Redi
 43
 44        // Redis pub/sub response channel: publisher + subscriber + the watchdog's liveness probe,
 45        // all one shared instance.
 43846        services.TryAddSingleton<RedisAsyncResponseChannel>();
 85147        services.Replace(ServiceDescriptor.Singleton<IAsyncResponsePublisher>(provider => provider.GetRequiredService<Re
 76648        services.Replace(ServiceDescriptor.Singleton<IRawAsyncResponsePublisher>(provider => provider.GetRequiredService
 79949        services.Replace(ServiceDescriptor.Singleton<IAsyncResponseSubscriber>(provider => provider.GetRequiredService<R
 77550        services.Replace(ServiceDescriptor.Singleton<IRecoverableAsyncResponseSubscriber>(provider => provider.GetRequir
 77551        services.Replace(ServiceDescriptor.Singleton<IActiveSubscriberProbe>(provider => provider.GetRequiredService<Red
 52
 53        // Durable recovery capability: expose the recoverable fluent builder only when the Redis
 54        // channel package is the selected response channel. Plain IAsyncResponseBuilder still works
 55        // and shares the same implementation, but its static type does not offer recovery callbacks.
 77156        services.Replace(ServiceDescriptor.Singleton<IRecoverableAsyncResponseBuilder>(provider => new RecoverableAsyncR
 77157            provider.GetRequiredService<IRecoverableAsyncResponseSubscriber>(),
 77158            provider.GetService<IWorkerTransport>(),
 77159            provider.GetService<IAsyncResponseReplyTargetProvider>(),
 77160            provider.GetRequiredService<AsyncResponseContextPropagation>(),
 77161            provider.GetService<TimeProvider>(),
 77162            // The producer-side mirror of the ingress's inbound size budget (WorkerJobTooLargeException).
 77163            provider.GetService<IOptions<AsyncResponseOptions>>())));
 77164        services.Replace(ServiceDescriptor.Singleton<IAsyncResponseBuilder>(provider => provider.GetRequiredService<IRec
 65
 66        // The resolved default waiter timeout is declared through the marker so the startup
 67        // validator can require the durable-flow ledger TTL to out-live a timeout-less awaited
 68        // step, and the flow engine can extend a parked ledger by it — without either referencing
 69        // channel option types.
 43870        services.AddSingleton(provider =>
 43871        {
 33572            var options = provider.GetRequiredService<Microsoft.Extensions.Options.IOptions<RedisAsyncResponseOptions>>(
 33573            return new AsyncResponseChannelMarker("Redis")
 33574            {
 33575                EffectiveDefaultWaitTimeout = options.DefaultTimeout ?? options.RecoveryStateExpiry
 33576            };
 43877        });
 43878        return builder;
 79    }
 80}