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

Information
Class: AsyncResponse.Transports.RabbitMQ.RabbitMqTopology
Assembly: AsyncResponse.Transports.RabbitMQ
File(s): /home/runner/work/AsyncResponse/AsyncResponse/src/Transports/AsyncResponse.Transports.RabbitMQ/RabbitMqTopology.cs
Line coverage
100%
Covered lines: 52
Uncovered lines: 0
Coverable lines: 52
Total lines: 121
Line coverage: 100%
Branch coverage
100%
Covered branches: 16
Total branches: 16
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
EnsureWorkerAsync(...)100%22100%
EnsureResponseAsync(...)100%22100%
DeclareQueueTopologyAsync()100%11100%
EnsureDeadLetterTopologyAsync()100%88100%
CreatePersistentJsonProperties(...)100%44100%

File(s)

/home/runner/work/AsyncResponse/AsyncResponse/src/Transports/AsyncResponse.Transports.RabbitMQ/RabbitMqTopology.cs

#LineLine coverage
 1using RabbitMQ.Client;
 2
 3namespace AsyncResponse.Transports.RabbitMQ;
 4
 5internal static class RabbitMqTopology
 6{
 7    private const string DirectExchange = "direct";
 8
 9    /// <summary>Ensures the required resource exists.</summary>
 10    public static Task EnsureWorkerAsync(
 11        IRabbitMqChannel channel,
 12        RabbitMqAsyncResponseOptions options,
 13        CancellationToken cancellationToken = default)
 14    {
 315        if (!options.DeclareTopology)
 316            return Task.CompletedTask;
 17
 318        var exchange = RabbitMqOptionsValidator.Required(options.WorkerExchange, nameof(options.WorkerExchange));
 319        var queue = RabbitMqOptionsValidator.Required(options.WorkerQueue, nameof(options.WorkerQueue));
 320        var routingKey = RabbitMqOptionsValidator.Required(options.WorkerRoutingKey, nameof(options.WorkerRoutingKey));
 21
 322        return DeclareQueueTopologyAsync(channel, options, exchange, queue, routingKey, cancellationToken);
 23    }
 24
 25    /// <summary>Ensures the required resource exists.</summary>
 26    public static Task EnsureResponseAsync(
 27        IRabbitMqChannel channel,
 28        RabbitMqAsyncResponseOptions options,
 29        CancellationToken cancellationToken = default)
 30    {
 331        if (!options.DeclareTopology)
 332            return Task.CompletedTask;
 33
 334        var exchange = RabbitMqOptionsValidator.Required(options.ResponseExchange, nameof(options.ResponseExchange));
 335        var queue = RabbitMqOptionsValidator.Required(options.ResponseQueue, nameof(options.ResponseQueue));
 336        var routingKey = RabbitMqOptionsValidator.Required(options.ResponseRoutingKey, nameof(options.ResponseRoutingKey
 37
 338        return DeclareQueueTopologyAsync(channel, options, exchange, queue, routingKey, cancellationToken);
 39    }
 40
 41    private static async Task DeclareQueueTopologyAsync(
 42        IRabbitMqChannel channel,
 43        RabbitMqAsyncResponseOptions options,
 44        string exchange,
 45        string queue,
 46        string routingKey,
 47        CancellationToken cancellationToken)
 48    {
 349        await channel.ExchangeDeclareAsync(exchange, DirectExchange, durable: true, autoDelete: false, cancellationToken
 50
 351        var queueArguments = await EnsureDeadLetterTopologyAsync(channel, options, routingKey, cancellationToken).Config
 52
 353        await channel.QueueDeclareAsync(queue, durable: true, exclusive: false, autoDelete: false, queueArguments, cance
 354        await channel.QueueBindAsync(queue, exchange, routingKey, cancellationToken).ConfigureAwait(false);
 355    }
 56
 57    /// <summary>
 58    /// Declares the dead-letter exchange/queue/binding when configured and returns the arguments to apply to the
 59    /// source queue (<c>x-dead-letter-exchange</c> and optionally <c>x-dead-letter-routing-key</c>), or null when
 60    /// no dead-letter exchange is configured.
 61    /// </summary>
 62    private static async Task<IDictionary<string, object?>?> EnsureDeadLetterTopologyAsync(
 63        IRabbitMqChannel channel,
 64        RabbitMqAsyncResponseOptions options,
 65        string sourceRoutingKey,
 66        CancellationToken cancellationToken)
 67    {
 368        if (string.IsNullOrWhiteSpace(options.DeadLetterExchange))
 369            return null;
 70
 271        var deadLetterExchange = options.DeadLetterExchange;
 272        await channel.ExchangeDeclareAsync(deadLetterExchange, DirectExchange, durable: true, autoDelete: false, cancell
 73
 274        if (!string.IsNullOrWhiteSpace(options.DeadLetterQueue))
 75        {
 276            var bindingRoutingKey = string.IsNullOrWhiteSpace(options.DeadLetterRoutingKey)
 277                ? sourceRoutingKey
 278                : options.DeadLetterRoutingKey;
 79
 280            await channel.QueueDeclareAsync(options.DeadLetterQueue, durable: true, exclusive: false, autoDelete: false,
 281            await channel.QueueBindAsync(options.DeadLetterQueue, deadLetterExchange, bindingRoutingKey, cancellationTok
 282        }
 83
 284        var arguments = new Dictionary<string, object?>(StringComparer.Ordinal)
 285        {
 286            ["x-dead-letter-exchange"] = deadLetterExchange
 287        };
 88
 289        if (!string.IsNullOrWhiteSpace(options.DeadLetterRoutingKey))
 290            arguments["x-dead-letter-routing-key"] = options.DeadLetterRoutingKey;
 91
 292        return arguments;
 393    }
 94
 95    /// <summary>Creates the requested resource.</summary>
 96    public static BasicProperties CreatePersistentJsonProperties(string? correlationId, string correlationHeader)
 97    {
 398        var properties = new BasicProperties
 399        {
 3100            ContentType = "application/json",
 3101            DeliveryMode = DeliveryModes.Persistent,
 3102            Persistent = true,
 3103            MessageId = Guid.NewGuid().ToString("N"),
 3104            Timestamp = new AmqpTimestamp(DateTimeOffset.UtcNow.ToUnixTimeSeconds())
 3105        };
 106
 3107        if (!string.IsNullOrWhiteSpace(correlationId))
 108        {
 3109            properties.CorrelationId = correlationId;
 3110            if (!string.IsNullOrWhiteSpace(correlationHeader))
 111            {
 3112                properties.Headers = new Dictionary<string, object?>(StringComparer.Ordinal)
 3113                {
 3114                    [correlationHeader] = correlationId
 3115                };
 116            }
 117        }
 118
 3119        return properties;
 120    }
 121}