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

Information
Class: AsyncResponse.Transports.Redis.RedisReplyTargetProvider
Assembly: AsyncResponse.Transports.Redis
File(s): /_/src/Transports/AsyncResponse.Transports.Redis/RedisReplyTargetProvider.cs
Line coverage
100%
Covered lines: 45
Uncovered lines: 0
Coverable lines: 45
Total lines: 76
Line coverage: 100%
Branch coverage
100%
Covered branches: 12
Total branches: 12
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
GetReplyTarget(...)100%88100%
ResolveTarget(...)100%44100%

File(s)

/_/src/Transports/AsyncResponse.Transports.Redis/RedisReplyTargetProvider.cs

#LineLine coverage
 1using Microsoft.Extensions.Options;
 2
 3namespace AsyncResponse.Transports.Redis;
 4
 2085internal sealed class RedisReplyTargetProvider(
 2086    IOptions<RedisAsyncResponseTransportOptions> _options) : IAsyncResponseReplyTargetProvider
 7{
 8    /// <summary>Gets the configured reply target.</summary>
 9    public AsyncResponseReplyTarget GetReplyTarget(string? name = null)
 10    {
 1411        var options = _options.Value;
 1412        RedisTransportOptionsValidator.ValidateCommon(options);
 1413        var schema = new RedisTransportKeySchema(options);
 1414        var targetName = string.IsNullOrWhiteSpace(name)
 1415            ? options.DefaultReplyTargetName
 1416            : name;
 17
 1418        var target = ResolveTarget(options, schema, targetName);
 1219        var responseStream = RedisTransportOptionsValidator.Required(
 1220            target.ResponseStream,
 1221            $"{nameof(RedisReplyTargetOptions)}.{nameof(RedisReplyTargetOptions.ResponseStream)}");
 1222        var consumerGroup = target.ConsumerGroup ?? options.ResponseConsumerGroup;
 23
 24        // ValidateCommon enforces distinctness for the transport-wide streams; a NAMED target
 25        // must honor the same rule (DB-transport parity) — aimed at the worker or dead-letter
 26        // stream, its responses are consumed as worker jobs (or mixed into dead letters) while
 27        // the waiter times out.
 1228        if (StringComparer.Ordinal.Equals(responseStream, schema.WorkerStream.ToString())
 1229            || StringComparer.Ordinal.Equals(responseStream, schema.DeadLetterStream.ToString()))
 30        {
 431            throw new InvalidOperationException(
 432                $"Redis async-response reply target '{targetName}' uses stream '{responseStream}', which collides with "
 433                $"{nameof(RedisAsyncResponseTransportOptions.WorkerStream)} or {nameof(RedisAsyncResponseTransportOption
 434                "its responses would be consumed as worker jobs (or mixed into dead letters).");
 35        }
 36
 837        var properties = new Dictionary<string, string>(target.Properties, StringComparer.Ordinal)
 838        {
 839            ["stream"] = responseStream,
 840            ["consumerGroup"] = consumerGroup,
 841            ["payloadField"] = options.PayloadField,
 842            ["correlationIdField"] = options.CorrelationIdField
 843        };
 44
 845        return new AsyncResponseReplyTarget
 846        {
 847            Name = targetName,
 848            Transport = RedisAsyncResponseTransportOptions.TransportName,
 849            Address = responseStream,
 850            Properties = properties
 851        };
 52    }
 53
 54    private static RedisReplyTargetOptions ResolveTarget(
 55        RedisAsyncResponseTransportOptions options,
 56        RedisTransportKeySchema schema,
 57        string targetName)
 58    {
 1459        if (options.ReplyTargets.TryGetValue(targetName, out var configured))
 860            return configured;
 61
 662        if (StringComparer.Ordinal.Equals(targetName, options.DefaultReplyTargetName))
 63        {
 464            return new RedisReplyTargetOptions
 465            {
 466                ResponseStream = schema.ResponseStream.ToString(),
 467                ConsumerGroup = options.ResponseConsumerGroup
 468            };
 69        }
 70
 271        throw new InvalidOperationException(
 272            $"Redis async-response reply target '{targetName}' is not configured. " +
 273            $"Configure {nameof(RedisAsyncResponseTransportOptions.ResponseStream)} for the default target " +
 274            $"or add a named target with {nameof(RedisAsyncResponseTransportOptions.AddReplyTarget)}.");
 75    }
 76}