2021-09-27 12:42:46 +00:00
|
|
|
using System;
|
2020-06-01 20:26:03 +00:00
|
|
|
using System.Threading;
|
2020-05-25 14:31:56 +00:00
|
|
|
using System.Threading.Tasks;
|
2021-09-27 12:42:46 +00:00
|
|
|
using Microsoft.Extensions.Logging;
|
2020-05-25 14:31:56 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
namespace Wabbajack.Common;
|
|
|
|
|
|
|
|
public static class CircuitBreaker
|
2020-05-25 14:31:56 +00:00
|
|
|
{
|
2021-10-23 16:51:17 +00:00
|
|
|
public static TimeSpan DEFAULT_DELAY = TimeSpan.FromMilliseconds(100);
|
|
|
|
public static int DEFAULT_DELAY_MULTIPLIER = 2;
|
|
|
|
public static int DEFAULT_RETRIES = 5;
|
|
|
|
|
2022-01-10 04:09:47 +00:00
|
|
|
public static async ValueTask<TR> WithAutoRetryAsync<TR, TE>(ILogger logger, Func<Task<TR>> f,
|
2021-10-23 16:51:17 +00:00
|
|
|
TimeSpan? delay = null, int? multipler = null, int? maxRetries = null) where TE : Exception
|
2020-05-25 14:31:56 +00:00
|
|
|
{
|
2021-10-23 16:51:17 +00:00
|
|
|
var retries = 0;
|
|
|
|
delay ??= DEFAULT_DELAY;
|
|
|
|
multipler ??= DEFAULT_DELAY_MULTIPLIER;
|
|
|
|
maxRetries ??= DEFAULT_RETRIES;
|
2020-05-25 14:31:56 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
TOP:
|
|
|
|
try
|
2020-05-25 14:31:56 +00:00
|
|
|
{
|
2021-10-23 16:51:17 +00:00
|
|
|
return await f();
|
2020-05-25 14:31:56 +00:00
|
|
|
}
|
2021-10-23 16:51:17 +00:00
|
|
|
catch (TE ex)
|
2020-05-26 11:31:11 +00:00
|
|
|
{
|
2021-10-23 16:51:17 +00:00
|
|
|
retries += 1;
|
|
|
|
if (retries > maxRetries)
|
|
|
|
throw;
|
|
|
|
logger.LogWarning("(Retry {retries} of {maxRetries}), got exception {message}, waiting {wait}ms",
|
|
|
|
retries, maxRetries, ex.Message, delay!.Value.TotalMilliseconds);
|
|
|
|
await Task.Delay(delay.Value);
|
|
|
|
delay = delay * multipler;
|
|
|
|
goto TOP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-10 04:09:47 +00:00
|
|
|
public static async ValueTask WithAutoRetryAsync<TE>(ILogger logger, Func<Task> f, TimeSpan? delay = null,
|
2021-10-23 16:51:17 +00:00
|
|
|
int? multipler = null, int? maxRetries = null) where TE : Exception
|
|
|
|
{
|
|
|
|
var retries = 0;
|
|
|
|
delay ??= DEFAULT_DELAY;
|
|
|
|
multipler ??= DEFAULT_DELAY_MULTIPLIER;
|
|
|
|
maxRetries ??= DEFAULT_RETRIES;
|
2020-05-26 11:31:11 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
TOP:
|
|
|
|
try
|
|
|
|
{
|
|
|
|
await f();
|
2021-03-11 02:28:28 +00:00
|
|
|
}
|
2021-10-23 16:51:17 +00:00
|
|
|
catch (TE ex)
|
2021-03-11 02:28:28 +00:00
|
|
|
{
|
2021-10-23 16:51:17 +00:00
|
|
|
retries += 1;
|
|
|
|
if (retries > maxRetries)
|
|
|
|
throw;
|
|
|
|
logger.LogWarning("(Retry {retries} of {maxRetries}), got exception {message}, waiting {wait}ms",
|
|
|
|
retries, maxRetries, ex.Message, delay!.Value.TotalMilliseconds);
|
|
|
|
await Task.Delay(delay.Value);
|
|
|
|
delay = delay * multipler;
|
|
|
|
goto TOP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-11 02:28:28 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
public static async ValueTask WithAutoRetryAllAsync(ILogger logger, Func<ValueTask> f, TimeSpan? delay = null,
|
|
|
|
int? multipler = null, int? maxRetries = null)
|
|
|
|
{
|
|
|
|
var retries = 0;
|
|
|
|
delay ??= DEFAULT_DELAY;
|
|
|
|
multipler ??= DEFAULT_DELAY_MULTIPLIER;
|
|
|
|
maxRetries ??= DEFAULT_RETRIES;
|
|
|
|
|
|
|
|
TOP:
|
|
|
|
try
|
|
|
|
{
|
|
|
|
await f();
|
2021-03-11 02:28:28 +00:00
|
|
|
}
|
2021-10-23 16:51:17 +00:00
|
|
|
catch (Exception ex)
|
2021-03-11 02:28:28 +00:00
|
|
|
{
|
2021-10-23 16:51:17 +00:00
|
|
|
retries += 1;
|
|
|
|
if (retries > maxRetries)
|
|
|
|
throw;
|
|
|
|
logger.LogWarning("(Retry {retries} of {maxRetries}), got exception {message}, waiting {wait}ms",
|
|
|
|
retries, maxRetries, ex.Message, delay!.Value.TotalMilliseconds);
|
|
|
|
await Task.Delay(delay.Value);
|
|
|
|
delay = delay * multipler;
|
|
|
|
goto TOP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static async ValueTask<T> WithAutoRetryAllAsync<T>(ILogger logger, Func<ValueTask<T>> f,
|
|
|
|
TimeSpan? delay = null, int? multipler = null, int? maxRetries = null)
|
|
|
|
{
|
|
|
|
var retries = 0;
|
|
|
|
delay ??= DEFAULT_DELAY;
|
|
|
|
multipler ??= DEFAULT_DELAY_MULTIPLIER;
|
|
|
|
maxRetries ??= DEFAULT_RETRIES;
|
2021-03-11 02:28:28 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
TOP:
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return await f();
|
2020-05-26 11:31:11 +00:00
|
|
|
}
|
2021-10-23 16:51:17 +00:00
|
|
|
catch (Exception ex)
|
2020-06-01 20:26:03 +00:00
|
|
|
{
|
2021-10-23 16:51:17 +00:00
|
|
|
retries += 1;
|
|
|
|
if (retries > maxRetries)
|
|
|
|
throw;
|
|
|
|
await Task.Delay(delay.Value);
|
|
|
|
logger.LogWarning("(Retry {retries} of {maxRetries}), got exception {message}, waiting {wait}ms",
|
|
|
|
retries, maxRetries, ex.Message, delay!.Value.TotalMilliseconds);
|
|
|
|
delay = delay * multipler;
|
|
|
|
goto TOP;
|
2020-06-01 20:26:03 +00:00
|
|
|
}
|
2021-10-23 16:51:17 +00:00
|
|
|
}
|
2020-05-25 14:31:56 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
public static void WithAutoRetry<TE>(ILogger logger, Action f, TimeSpan? delay = null, int? multipler = null,
|
|
|
|
int? maxRetries = null) where TE : Exception
|
|
|
|
{
|
|
|
|
var retries = 0;
|
|
|
|
delay ??= DEFAULT_DELAY;
|
|
|
|
multipler ??= DEFAULT_DELAY_MULTIPLIER;
|
|
|
|
maxRetries ??= DEFAULT_RETRIES;
|
|
|
|
|
|
|
|
TOP:
|
|
|
|
try
|
|
|
|
{
|
|
|
|
f();
|
|
|
|
}
|
|
|
|
catch (TE ex)
|
|
|
|
{
|
|
|
|
retries += 1;
|
|
|
|
if (retries > maxRetries)
|
|
|
|
throw;
|
|
|
|
logger.LogWarning("(Retry {retries} of {maxRetries}), got exception {message}, waiting {wait}ms",
|
|
|
|
retries, maxRetries, ex.Message, delay!.Value.TotalMilliseconds);
|
|
|
|
Thread.Sleep(delay.Value);
|
|
|
|
delay = delay * multipler;
|
|
|
|
goto TOP;
|
|
|
|
}
|
2020-05-25 14:31:56 +00:00
|
|
|
}
|
2021-09-27 12:42:46 +00:00
|
|
|
}
|