< Summary

Information
Class: AsiBackbone.Core.Emissions.GovernanceEmissionResult
Assembly: AsiBackbone.Core
File(s): /home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/Emissions/GovernanceEmissionResult.cs
Line coverage
98%
Covered lines: 90
Uncovered lines: 1
Coverable lines: 91
Total lines: 237
Line coverage: 98.9%
Branch coverage
84%
Covered branches: 37
Total branches: 44
Branch coverage: 84%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
.ctor(...)75%4493.75%
get_Status()100%11100%
get_ProviderName()100%11100%
get_ProviderRecordId()100%11100%
get_RetryAfterUtc()100%11100%
get_Error()100%11100%
get_Metadata()100%11100%
get_IsSuccess()100%11100%
get_ShouldRetry()100%88100%
get_IsTerminal()100%44100%
get_HasMetadata()100%11100%
Pending(...)100%11100%
Delivered(...)100%11100%
Deferred(...)100%44100%
Failed(...)50%22100%
RetryableFailure(...)50%22100%
DeadLettered(...)50%22100%
DeliveredFromNormalizedMetadata(...)50%22100%
NormalizeOptional(...)100%22100%
NormalizeMetadata(...)85.71%1414100%

File(s)

/home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/Emissions/GovernanceEmissionResult.cs

#LineLine coverage
 1using System.Collections.ObjectModel;
 2
 3namespace AsiBackbone.Core.Emissions;
 4
 5/// <summary>
 6/// Represents the provider-neutral result of a governance emission attempt.
 7/// </summary>
 8public sealed class GovernanceEmissionResult
 9{
 510    private static readonly IReadOnlyDictionary<string, string> EmptyMetadata =
 511        new ReadOnlyDictionary<string, string>(
 512            new Dictionary<string, string>(StringComparer.Ordinal));
 13
 22414    private GovernanceEmissionResult(
 22415        GovernanceEmissionStatus status,
 22416        string? providerName,
 22417        string? providerRecordId,
 22418        DateTimeOffset? retryAfterUtc,
 22419        GovernanceEmissionError? error,
 22420        IReadOnlyDictionary<string, string> metadata)
 21    {
 22422        if (!Enum.IsDefined(status))
 23        {
 024            throw new ArgumentOutOfRangeException(nameof(status), status, "Emission status must be defined.");
 25        }
 26
 22427        Status = status;
 22428        ProviderName = NormalizeOptional(providerName);
 22429        ProviderRecordId = NormalizeOptional(providerRecordId);
 22430        RetryAfterUtc = retryAfterUtc?.ToUniversalTime();
 22431        Error = error;
 22432        Metadata = metadata;
 22433    }
 34
 35    /// <summary>
 36    /// Gets the provider-neutral result status.
 37    /// </summary>
 39638    public GovernanceEmissionStatus Status { get; }
 39
 40    /// <summary>
 41    /// Gets the provider name that handled or attempted the emission, when available.
 42    /// </summary>
 11243    public string? ProviderName { get; }
 44
 45    /// <summary>
 46    /// Gets the provider-side record identifier, when one is returned and safe to keep.
 47    /// </summary>
 8448    public string? ProviderRecordId { get; }
 49
 50    /// <summary>
 51    /// Gets the UTC retry timestamp for deferred or retryable outcomes, when supplied.
 52    /// </summary>
 5453    public DateTimeOffset? RetryAfterUtc { get; }
 54
 55    /// <summary>
 56    /// Gets provider-neutral error information, when the emission did not deliver successfully.
 57    /// </summary>
 8258    public GovernanceEmissionError? Error { get; }
 59
 60    /// <summary>
 61    /// Gets minimized provider-neutral result metadata.
 62    /// </summary>
 12063    public IReadOnlyDictionary<string, string> Metadata { get; }
 64
 65    /// <summary>
 66    /// Gets a value indicating whether the emission was delivered successfully.
 67    /// </summary>
 20268    public bool IsSuccess => Status is GovernanceEmissionStatus.Delivered;
 69
 70    /// <summary>
 71    /// Gets a value indicating whether the emission should be retried according to provider-neutral status or error met
 72    /// </summary>
 3473    public bool ShouldRetry => Status is GovernanceEmissionStatus.Deferred or GovernanceEmissionStatus.RetryableFailure
 3474        || Error?.IsRetryable == true;
 75
 76    /// <summary>
 77    /// Gets a value indicating whether the result is terminal and should not be retried automatically.
 78    /// </summary>
 2279    public bool IsTerminal => Status is GovernanceEmissionStatus.Delivered or GovernanceEmissionStatus.DeadLettered;
 80
 81    /// <summary>
 82    /// Gets a value indicating whether result metadata is present.
 83    /// </summary>
 1284    public bool HasMetadata => Metadata.Count > 0;
 85
 86    /// <summary>
 87    /// Creates a pending emission result.
 88    /// </summary>
 89    public static GovernanceEmissionResult Pending(
 90        string? providerName = null,
 91        IReadOnlyDictionary<string, string>? metadata = null)
 92    {
 1893        return new GovernanceEmissionResult(
 1894            GovernanceEmissionStatus.Pending,
 1895            providerName,
 1896            providerRecordId: null,
 1897            retryAfterUtc: null,
 1898            error: null,
 1899            NormalizeMetadata(metadata));
 100    }
 101
 102    /// <summary>
 103    /// Creates a delivered emission result.
 104    /// </summary>
 105    public static GovernanceEmissionResult Delivered(
 106        string? providerName = null,
 107        string? providerRecordId = null,
 108        IReadOnlyDictionary<string, string>? metadata = null)
 109    {
 128110        return DeliveredFromNormalizedMetadata(
 128111            providerName,
 128112            providerRecordId,
 128113            NormalizeMetadata(metadata));
 114    }
 115
 116    /// <summary>
 117    /// Creates a deferred emission result.
 118    /// </summary>
 119    public static GovernanceEmissionResult Deferred(
 120        GovernanceEmissionError? error = null,
 121        DateTimeOffset? retryAfterUtc = null,
 122        string? providerName = null,
 123        IReadOnlyDictionary<string, string>? metadata = null)
 124    {
 18125        return new GovernanceEmissionResult(
 18126            GovernanceEmissionStatus.Deferred,
 18127            providerName ?? error?.ProviderName,
 18128            providerRecordId: null,
 18129            retryAfterUtc,
 18130            error,
 18131            NormalizeMetadata(metadata));
 132    }
 133
 134    /// <summary>
 135    /// Creates a failed emission result.
 136    /// </summary>
 137    public static GovernanceEmissionResult Failed(
 138        GovernanceEmissionError error,
 139        string? providerName = null,
 140        IReadOnlyDictionary<string, string>? metadata = null)
 141    {
 30142        ArgumentNullException.ThrowIfNull(error);
 143
 26144        return new GovernanceEmissionResult(
 26145            GovernanceEmissionStatus.Failed,
 26146            providerName ?? error.ProviderName,
 26147            providerRecordId: null,
 26148            retryAfterUtc: null,
 26149            error,
 26150            NormalizeMetadata(metadata));
 151    }
 152
 153    /// <summary>
 154    /// Creates a retryable failure emission result.
 155    /// </summary>
 156    public static GovernanceEmissionResult RetryableFailure(
 157        GovernanceEmissionError error,
 158        DateTimeOffset? retryAfterUtc = null,
 159        string? providerName = null,
 160        IReadOnlyDictionary<string, string>? metadata = null)
 161    {
 20162        ArgumentNullException.ThrowIfNull(error);
 163
 16164        return new GovernanceEmissionResult(
 16165            GovernanceEmissionStatus.RetryableFailure,
 16166            providerName ?? error.ProviderName,
 16167            providerRecordId: null,
 16168            retryAfterUtc,
 16169            error,
 16170            NormalizeMetadata(metadata));
 171    }
 172
 173    /// <summary>
 174    /// Creates a dead-letter emission result.
 175    /// </summary>
 176    public static GovernanceEmissionResult DeadLettered(
 177        GovernanceEmissionError error,
 178        string? providerName = null,
 179        IReadOnlyDictionary<string, string>? metadata = null)
 180    {
 18181        ArgumentNullException.ThrowIfNull(error);
 182
 14183        return new GovernanceEmissionResult(
 14184            GovernanceEmissionStatus.DeadLettered,
 14185            providerName ?? error.ProviderName,
 14186            providerRecordId: null,
 14187            retryAfterUtc: null,
 14188            error,
 14189            NormalizeMetadata(metadata));
 190    }
 191
 192    internal static GovernanceEmissionResult DeliveredFromNormalizedMetadata(
 193        string? providerName = null,
 194        string? providerRecordId = null,
 195        IReadOnlyDictionary<string, string>? normalizedMetadata = null)
 196    {
 132197        return new GovernanceEmissionResult(
 132198            GovernanceEmissionStatus.Delivered,
 132199            providerName,
 132200            providerRecordId,
 132201            retryAfterUtc: null,
 132202            error: null,
 132203            normalizedMetadata ?? EmptyMetadata);
 204    }
 205
 206    private static string? NormalizeOptional(string? value)
 207    {
 448208        return string.IsNullOrWhiteSpace(value)
 448209            ? null
 448210            : value.Trim();
 211    }
 212
 213    private static IReadOnlyDictionary<string, string> NormalizeMetadata(
 214        IReadOnlyDictionary<string, string>? metadata)
 215    {
 220216        if (metadata is null || metadata.Count == 0)
 217        {
 170218            return EmptyMetadata;
 219        }
 220
 50221        Dictionary<string, string> normalizedMetadata = new(metadata.Count, StringComparer.Ordinal);
 222
 388223        foreach (KeyValuePair<string, string> item in metadata)
 224        {
 144225            if (string.IsNullOrWhiteSpace(item.Key))
 226            {
 227                continue;
 228            }
 229
 134230            normalizedMetadata[item.Key.Trim()] = item.Value?.Trim() ?? string.Empty;
 231        }
 232
 50233        return normalizedMetadata.Count == 0
 50234            ? EmptyMetadata
 50235            : new ReadOnlyDictionary<string, string>(normalizedMetadata);
 236    }
 237}

Methods/Properties

.cctor()
.ctor(AsiBackbone.Core.Emissions.GovernanceEmissionStatus,System.String,System.String,System.Nullable`1<System.DateTimeOffset>,AsiBackbone.Core.Emissions.GovernanceEmissionError,System.Collections.Generic.IReadOnlyDictionary`2<System.String,System.String>)
get_Status()
get_ProviderName()
get_ProviderRecordId()
get_RetryAfterUtc()
get_Error()
get_Metadata()
get_IsSuccess()
get_ShouldRetry()
get_IsTerminal()
get_HasMetadata()
Pending(System.String,System.Collections.Generic.IReadOnlyDictionary`2<System.String,System.String>)
Delivered(System.String,System.String,System.Collections.Generic.IReadOnlyDictionary`2<System.String,System.String>)
Deferred(AsiBackbone.Core.Emissions.GovernanceEmissionError,System.Nullable`1<System.DateTimeOffset>,System.String,System.Collections.Generic.IReadOnlyDictionary`2<System.String,System.String>)
Failed(AsiBackbone.Core.Emissions.GovernanceEmissionError,System.String,System.Collections.Generic.IReadOnlyDictionary`2<System.String,System.String>)
RetryableFailure(AsiBackbone.Core.Emissions.GovernanceEmissionError,System.Nullable`1<System.DateTimeOffset>,System.String,System.Collections.Generic.IReadOnlyDictionary`2<System.String,System.String>)
DeadLettered(AsiBackbone.Core.Emissions.GovernanceEmissionError,System.String,System.Collections.Generic.IReadOnlyDictionary`2<System.String,System.String>)
DeliveredFromNormalizedMetadata(System.String,System.String,System.Collections.Generic.IReadOnlyDictionary`2<System.String,System.String>)
NormalizeOptional(System.String)
NormalizeMetadata(System.Collections.Generic.IReadOnlyDictionary`2<System.String,System.String>)