54 lines
1.7 KiB
C#
54 lines
1.7 KiB
C#
using System;
|
|
using System.Net;
|
|
using System.Net.Http;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace HikvisionAttendanceService;
|
|
|
|
/// <summary>Exponential backoff retries for transient HTTP / network failures.</summary>
|
|
internal static class UserSyncRetryHelper
|
|
{
|
|
/// <summary>0-based attempt index: delays 1s, 2s, 4s, ... capped at 30s.</summary>
|
|
public static int GetBackoffDelayMilliseconds(int zeroBasedAttemptIndex)
|
|
{
|
|
if (zeroBasedAttemptIndex < 0)
|
|
zeroBasedAttemptIndex = 0;
|
|
double seconds = Math.Pow(2, zeroBasedAttemptIndex);
|
|
var ms = (int)(seconds * 1000);
|
|
return Math.Min(ms, 30_000);
|
|
}
|
|
|
|
/// <summary>Returns true if the HTTP status may succeed on retry.</summary>
|
|
public static bool IsTransientHttpStatus(HttpStatusCode code)
|
|
{
|
|
var n = (int)code;
|
|
if (n == 408 || n == 429)
|
|
return true;
|
|
if (n >= 500 && n <= 599)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
public static bool ShouldRetryException(Exception ex)
|
|
{
|
|
if (ex is HttpRequestException || ex is TaskCanceledException)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
public static void SleepBackoff(int zeroBasedAttemptIndex, CancellationToken ct)
|
|
{
|
|
ct.ThrowIfCancellationRequested();
|
|
var delay = GetBackoffDelayMilliseconds(zeroBasedAttemptIndex);
|
|
Thread.Sleep(delay);
|
|
ct.ThrowIfCancellationRequested();
|
|
}
|
|
|
|
public static async Task DelayBackoffAsync(int zeroBasedAttemptIndex, CancellationToken ct)
|
|
{
|
|
var delay = GetBackoffDelayMilliseconds(zeroBasedAttemptIndex);
|
|
await Task.Delay(delay, ct).ConfigureAwait(false);
|
|
}
|
|
}
|