< Summary

Information
Class: NostrSure.Infrastructure.Client.Implementation.RetryBackoffPolicy
Assembly: NostrSure.Infrastructure
File(s): /home/runner/work/NostrSure/NostrSure/NostrSure.Infrastructure/Client/Implementation/RetryBackoffPolicy.cs
Line coverage
100%
Covered lines: 28
Uncovered lines: 0
Coverable lines: 28
Total lines: 58
Line coverage: 100%
Branch coverage
91%
Covered branches: 11
Total branches: 12
Branch coverage: 91.6%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%44100%
DelayAsync()100%22100%
ShouldRetry(...)100%11100%
GetDelay(...)83.33%66100%

File(s)

/home/runner/work/NostrSure/NostrSure/NostrSure.Infrastructure/Client/Implementation/RetryBackoffPolicy.cs

#LineLine coverage
 1using NostrSure.Infrastructure.Client.Abstractions;
 2
 3namespace NostrSure.Infrastructure.Client.Implementation;
 4
 5/// <summary>
 6/// Retry policy with exponential backoff
 7/// </summary>
 8public class RetryBackoffPolicy : IHealthPolicy
 9{
 10    private readonly TimeSpan _baseDelay;
 11    private readonly TimeSpan _maxDelay;
 12    private readonly int _maxRetries;
 13    private readonly Random _jitterRandom;
 14
 4015    public RetryBackoffPolicy(
 4016        TimeSpan? baseDelay = null,
 4017        TimeSpan? maxDelay = null,
 4018        int maxRetries = 5)
 4019    {
 4020        _baseDelay = baseDelay ?? TimeSpan.FromSeconds(1);
 4021        _maxDelay = maxDelay ?? TimeSpan.FromMinutes(1);
 4022        _maxRetries = maxRetries;
 4023        _jitterRandom = new Random();
 4024    }
 25
 26    public async Task DelayAsync(int attempt, CancellationToken cancellationToken = default)
 327    {
 428        if (attempt <= 0) return;
 29
 230        var delay = GetDelay(attempt);
 231        await Task.Delay(delay, cancellationToken);
 232    }
 33
 34    public bool ShouldRetry(int attempt)
 1335    {
 1336        return attempt <= _maxRetries;
 1337    }
 38
 39    public TimeSpan GetDelay(int attempt)
 6940    {
 7241        if (attempt <= 0) return TimeSpan.Zero;
 42
 43        // Exponential backoff: baseDelay * 2^(attempt-1)
 6644        var exponentialDelay = TimeSpan.FromTicks(
 6645            _baseDelay.Ticks * (1L << Math.Min(attempt - 1, 10))); // Cap at 2^10 to prevent overflow
 46
 47        // Cap at max delay
 6648        var cappedDelay = exponentialDelay > _maxDelay ? _maxDelay : exponentialDelay;
 49
 50        // Add jitter (±25% of the delay)
 6651        var jitterRange = (int)(cappedDelay.TotalMilliseconds * 0.25);
 6652        var jitter = _jitterRandom.Next(-jitterRange, jitterRange + 1);
 6653        var finalDelay = cappedDelay.Add(TimeSpan.FromMilliseconds(jitter));
 54
 55        // Ensure non-negative
 6656        return finalDelay > TimeSpan.Zero ? finalDelay : TimeSpan.Zero;
 6957    }
 58}