< Summary

Information
Class: ArturRios.Data.MongoDb.Repositories.MongoErrors
Assembly: ArturRios.Data.MongoDb
File(s): /home/runner/work/dotnet-data/dotnet-data/src/ArturRios.Data.MongoDb/Repositories/MongoErrors.cs
Line coverage
83%
Covered lines: 20
Uncovered lines: 4
Coverable lines: 24
Total lines: 84
Line coverage: 83.3%
Branch coverage
64%
Covered branches: 22
Total branches: 34
Branch coverage: 64.7%
Method coverage
100%
Covered methods: 3
Fully covered methods: 1
Total methods: 3
Method coverage: 100%
Full method coverage: 33.3%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
IsUniqueViolation(...)64.28%171475%
IsTransient(...)57.14%161480%
Describe(...)83.33%66100%

File(s)

/home/runner/work/dotnet-data/dotnet-data/src/ArturRios.Data.MongoDb/Repositories/MongoErrors.cs

#LineLine coverage
 1using ArturRios.Data.MongoDb.Exceptions;
 2using MongoDB.Driver;
 3
 4namespace ArturRios.Data.MongoDb.Repositories;
 5
 6/// <summary>
 7///     Classification of MongoDB failures, and the caller-safe messages that replace driver text.
 8///     Driver messages name indexes, collections, key values and cluster endpoints, so they are used
 9///     for classification only and are never returned to the caller.
 10/// </summary>
 11public static class MongoErrors
 12{
 13    /// <summary>Message returned on an optimistic-concurrency conflict.</summary>
 14    public const string ConcurrencyMessage =
 15        "Concurrency conflict: the document was modified or removed by another process.";
 16
 17    /// <summary>Message returned when a write violates a unique index.</summary>
 18    public const string UniqueViolationMessage = "Conflict: a document with the same unique value already exists.";
 19
 20    /// <summary>Message returned when the failure is transient and the operation may be retried.</summary>
 21    public const string TransientMessage = "The data store is temporarily unavailable. Please retry.";
 22
 23    /// <summary>Message returned when an operation fails with no finer classification.</summary>
 24    public const string GenericMessage = "A data-access error occurred.";
 25
 26    // Server error codes for a duplicate key on a unique index.
 27    private const int DuplicateKeyCode = 11000;
 28    private const int DuplicateKeyOnUpdateCode = 11001;
 29
 30    /// <summary>Detects a duplicate-key (unique index) violation anywhere in the exception chain.</summary>
 31    /// <param name="ex">The exception caught by a guard.</param>
 32    /// <returns><c>true</c> when the failure is a duplicate-key violation.</returns>
 33    public static bool IsUniqueViolation(Exception ex)
 34    {
 2435        for (var current = ex; current is not null; current = current.InnerException)
 36        {
 837            var duplicate = current switch
 838            {
 439                MongoWriteException write => write.WriteError?.Category == ServerErrorCategory.DuplicateKey,
 040                MongoBulkWriteException bulk => bulk.WriteErrors.Any(e =>
 041                    e.Category == ServerErrorCategory.DuplicateKey),
 042                MongoCommandException command => command.Code is DuplicateKeyCode or DuplicateKeyOnUpdateCode,
 443                _ => false
 844            };
 45
 846            if (duplicate)
 47            {
 448                return true;
 49            }
 50        }
 51
 452        return false;
 53    }
 54
 55    /// <summary>Detects a failure the caller may retry: connection, election or timeout.</summary>
 56    /// <param name="ex">The exception caught by a guard.</param>
 57    /// <returns><c>true</c> when the failure is transient.</returns>
 58    public static bool IsTransient(Exception ex)
 59    {
 1660        for (var current = ex; current is not null; current = current.InnerException)
 61        {
 462            if (current is MongoConnectionException or MongoNodeIsRecoveringException
 463                or MongoNotPrimaryException or MongoExecutionTimeoutException or TimeoutException)
 64            {
 065                return true;
 66            }
 67        }
 68
 469        return false;
 70    }
 71
 72    /// <summary>
 73    ///     Classifies a failure and returns the caller-safe message for it. Never includes driver text.
 74    /// </summary>
 75    /// <param name="ex">The exception caught by a guard.</param>
 76    /// <returns>One of the caller-safe messages exposed by this class.</returns>
 1277    public static string Describe(Exception ex) => ex switch
 1278    {
 479        MongoConcurrencyException => ConcurrencyMessage,
 1280        _ when IsUniqueViolation(ex) => UniqueViolationMessage,
 481        _ when IsTransient(ex) => TransientMessage,
 482        _ => GenericMessage
 1283    };
 84}