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

Information
Class: AsyncResponse.Transports.MongoDB.MongoDbTransportOptionsValidator
Assembly: AsyncResponse.Transports.MongoDB
File(s): /home/runner/work/AsyncResponse/AsyncResponse/src/Transports/AsyncResponse.Transports.MongoDB/MongoDbTransportOptionsValidator.cs
Line coverage
100%
Covered lines: 64
Uncovered lines: 0
Coverable lines: 64
Total lines: 109
Line coverage: 100%
Branch coverage
100%
Covered branches: 42
Total branches: 42
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
ValidateCommon(...)100%1616100%
ValidateSubscriber(...)100%22100%
ValidateSubscriber(...)100%1212100%
Required(...)100%22100%
ValidateCollectionName(...)100%88100%
Positive(...)100%22100%

File(s)

/home/runner/work/AsyncResponse/AsyncResponse/src/Transports/AsyncResponse.Transports.MongoDB/MongoDbTransportOptionsValidator.cs

#LineLine coverage
 1namespace AsyncResponse.Transports.MongoDB;
 2
 3internal static class MongoDbTransportOptionsValidator
 4{
 5    public static void ValidateCommon(MongoDbAsyncResponseTransportOptions options)
 6    {
 37        ValidateCollectionName(options.MessageCollection, nameof(options.MessageCollection));
 38        Required(options.WorkerQueue, nameof(options.WorkerQueue));
 39        Required(options.ResponseQueue, nameof(options.ResponseQueue));
 310        Required(options.DeadLetterQueue, nameof(options.DeadLetterQueue));
 311        Required(options.CorrelationIdHeader, nameof(options.CorrelationIdHeader));
 312        Required(options.DefaultReplyTargetName, nameof(options.DefaultReplyTargetName));
 13
 14        // All three logical queues share one collection, distinguished only by the queue field. Equal
 15        // names would make subscribers consume each other's documents (or re-consume dead letters).
 316        if (StringComparer.Ordinal.Equals(options.WorkerQueue, options.ResponseQueue)
 317            || StringComparer.Ordinal.Equals(options.WorkerQueue, options.DeadLetterQueue)
 318            || StringComparer.Ordinal.Equals(options.ResponseQueue, options.DeadLetterQueue))
 19        {
 320            throw new InvalidOperationException(
 321                $"{nameof(MongoDbAsyncResponseTransportOptions)}.{nameof(options.WorkerQueue)}, " +
 322                $"{nameof(options.ResponseQueue)}, and {nameof(options.DeadLetterQueue)} must be distinct; they share on
 23        }
 24
 325        if (options.DeadLetterRetention is { } deadLetterRetention && deadLetterRetention <= TimeSpan.Zero)
 326            throw new InvalidOperationException($"{nameof(MongoDbAsyncResponseTransportOptions)}.{nameof(options.DeadLet
 27
 328        Positive(options.LockTimeout, nameof(options.LockTimeout));
 329        Positive(options.PublishRetryBaseDelay, nameof(options.PublishRetryBaseDelay));
 330        Positive(options.PublishRetryMaxDelay, nameof(options.PublishRetryMaxDelay));
 331        Positive(options.SubscriberRetryBaseDelay, nameof(options.SubscriberRetryBaseDelay));
 332        Positive(options.SubscriberRetryMaxDelay, nameof(options.SubscriberRetryMaxDelay));
 333        Positive(options.ShutdownTimeout, nameof(options.ShutdownTimeout));
 34
 335        if (options.PublishMaxAttempts <= 0)
 336            throw new InvalidOperationException($"{nameof(MongoDbAsyncResponseTransportOptions)}.{nameof(options.Publish
 337        if (options.PublishRetryBaseDelay > options.PublishRetryMaxDelay)
 338            throw new InvalidOperationException($"{nameof(MongoDbAsyncResponseTransportOptions)}.{nameof(options.Publish
 339        if (options.SubscriberRetryBaseDelay > options.SubscriberRetryMaxDelay)
 340            throw new InvalidOperationException($"{nameof(MongoDbAsyncResponseTransportOptions)}.{nameof(options.Subscri
 341    }
 42
 43    /// <summary>Validates the supplied subscriber options together with the transport-wide shutdown budget.</summary>
 44    public static void ValidateSubscriber(
 45        MongoDbAsyncResponseTransportOptions transportOptions,
 46        MongoDbSubscriberOptions subscriber,
 47        string role)
 48    {
 349        ValidateSubscriber(subscriber, role);
 50
 351        if (subscriber.AckMode is not MongoDbAckMode.AckAfterEnqueue)
 352            return;
 53
 54        // MongoDB spends the background drain plus the change-stream listen-task join
 55        // (ShutdownTimeout) at shutdown; both must fit inside the host budget.
 356        ShutdownBudgetValidator.Validate(
 357            "MongoDB",
 358            $"{nameof(MongoDbAsyncResponseTransportOptions)}.{nameof(transportOptions.HostShutdownTimeout)}",
 359            transportOptions.HostShutdownTimeout,
 360            ($"{nameof(MongoDbSubscriberOptions)}.{nameof(subscriber.BackgroundDrainTimeout)} ({role})", subscriber.Back
 361            ($"{nameof(MongoDbAsyncResponseTransportOptions)}.{nameof(transportOptions.ShutdownTimeout)}", transportOpti
 362    }
 63
 64    public static void ValidateSubscriber(MongoDbSubscriberOptions subscriber, string role)
 65    {
 366        if (subscriber.BatchSize <= 0)
 367            throw new InvalidOperationException($"{nameof(MongoDbSubscriberOptions)}.{nameof(subscriber.BatchSize)} ({ro
 368        if (subscriber.MaxDeliveryAttempts < 0)
 369            throw new InvalidOperationException($"{nameof(MongoDbSubscriberOptions)}.{nameof(subscriber.MaxDeliveryAttem
 70
 371        Positive(subscriber.RedeliveryDelay, $"{nameof(subscriber.RedeliveryDelay)} ({role})");
 372        Positive(subscriber.EmptyPollDelay, $"{nameof(subscriber.EmptyPollDelay)} ({role})");
 73
 374        switch (subscriber.AckMode)
 75        {
 76            case MongoDbAckMode.AckAfterHandlerCompletes:
 377                return;
 78            case MongoDbAckMode.AckAfterEnqueue:
 379                if (subscriber.BackgroundWorkerCount <= 0)
 380                    throw new InvalidOperationException($"{nameof(MongoDbSubscriberOptions)}.{nameof(subscriber.Backgrou
 381                if (subscriber.BackgroundQueueCapacity <= 0)
 382                    throw new InvalidOperationException($"{nameof(MongoDbSubscriberOptions)}.{nameof(subscriber.Backgrou
 383                Positive(subscriber.BackgroundDrainTimeout, $"{nameof(subscriber.BackgroundDrainTimeout)} ({role})");
 384                return;
 85            default:
 386                throw new InvalidOperationException($"{nameof(MongoDbSubscriberOptions)}.{nameof(subscriber.AckMode)} ({
 87        }
 88    }
 89
 90    public static string Required(string? value, string name)
 391        => !string.IsNullOrWhiteSpace(value)
 392            ? value
 393            : throw new InvalidOperationException($"{nameof(MongoDbAsyncResponseTransportOptions)}.{name} must be config
 94
 95    public static void ValidateCollectionName(string? value, string name)
 96    {
 397        if (string.IsNullOrWhiteSpace(value))
 398            throw new InvalidOperationException($"{nameof(MongoDbAsyncResponseTransportOptions)}.{name} must be configur
 399        if (value.Contains('$') || value.Contains('\0') || value.StartsWith("system.", StringComparison.Ordinal))
 3100            throw new InvalidOperationException(
 3101                $"{nameof(MongoDbAsyncResponseTransportOptions)}.{name} '{value}' must be a valid MongoDB collection nam
 3102    }
 103
 104    private static void Positive(TimeSpan value, string name)
 105    {
 3106        if (value <= TimeSpan.Zero)
 3107            throw new InvalidOperationException($"{nameof(MongoDbAsyncResponseTransportOptions)}.{name} must be positive
 3108    }
 109}