61 lines
1.7 KiB
C#
61 lines
1.7 KiB
C#
using System.Net;
|
|
using System.Net.Http;
|
|
|
|
namespace Zcbot.WindowsNode;
|
|
|
|
internal enum TransferFailureKind
|
|
{
|
|
Authentication,
|
|
Transient,
|
|
Permanent,
|
|
Cancelled,
|
|
}
|
|
|
|
internal static class TransferRetryPolicy
|
|
{
|
|
private static readonly TimeSpan[] DownloadBackoff =
|
|
[
|
|
TimeSpan.FromMilliseconds(250),
|
|
TimeSpan.FromSeconds(1),
|
|
TimeSpan.FromSeconds(3),
|
|
];
|
|
|
|
internal static TransferFailureKind Classify(HttpStatusCode statusCode)
|
|
{
|
|
if (statusCode is HttpStatusCode.Unauthorized or HttpStatusCode.Forbidden)
|
|
{
|
|
return TransferFailureKind.Authentication;
|
|
}
|
|
if (statusCode is HttpStatusCode.RequestTimeout
|
|
or HttpStatusCode.TooManyRequests
|
|
|| (int)statusCode >= 500)
|
|
{
|
|
return TransferFailureKind.Transient;
|
|
}
|
|
return TransferFailureKind.Permanent;
|
|
}
|
|
|
|
internal static TransferFailureKind Classify(Exception exception) => exception switch
|
|
{
|
|
OperationCanceledException => TransferFailureKind.Cancelled,
|
|
HttpRequestException or IOException => TransferFailureKind.Transient,
|
|
_ => TransferFailureKind.Permanent,
|
|
};
|
|
|
|
internal static TimeSpan? RetryDelay(
|
|
HttpMethod method,
|
|
int attempt,
|
|
HttpStatusCode? statusCode = null,
|
|
Exception? exception = null)
|
|
{
|
|
if (method != HttpMethod.Get || attempt >= DownloadBackoff.Length)
|
|
{
|
|
return null;
|
|
}
|
|
var kind = statusCode is HttpStatusCode status
|
|
? Classify(status)
|
|
: exception is not null ? Classify(exception) : TransferFailureKind.Permanent;
|
|
return kind == TransferFailureKind.Transient ? DownloadBackoff[attempt] : null;
|
|
}
|
|
}
|