2019-10-10 17:19:28 +02:00
|
|
|
|
using System;
|
|
|
|
|
using System.Threading.Tasks;
|
2023-04-06 06:57:32 +02:00
|
|
|
|
using Microsoft.Data.SqlClient;
|
2019-10-10 17:19:28 +02:00
|
|
|
|
|
|
|
|
|
namespace Tapeti.Flow.SQL
|
|
|
|
|
{
|
|
|
|
|
internal class SqlRetryHelper
|
|
|
|
|
{
|
|
|
|
|
public static readonly TimeSpan[] ExponentialBackoff = {
|
|
|
|
|
TimeSpan.FromSeconds(1),
|
|
|
|
|
TimeSpan.FromSeconds(2),
|
|
|
|
|
TimeSpan.FromSeconds(3),
|
|
|
|
|
TimeSpan.FromSeconds(5),
|
|
|
|
|
TimeSpan.FromSeconds(8),
|
|
|
|
|
TimeSpan.FromSeconds(13),
|
|
|
|
|
TimeSpan.FromSeconds(21),
|
|
|
|
|
TimeSpan.FromSeconds(34),
|
|
|
|
|
TimeSpan.FromSeconds(55)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static async Task Execute(Func<Task> callback)
|
|
|
|
|
{
|
|
|
|
|
var retryAttempt = 0;
|
|
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2024-04-08 14:20:15 +02:00
|
|
|
|
await callback().ConfigureAwait(false);
|
2019-10-10 17:19:28 +02:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
catch (SqlException e)
|
|
|
|
|
{
|
|
|
|
|
if (SqlExceptionHelper.IsTransientError(e))
|
|
|
|
|
{
|
2024-04-08 14:20:15 +02:00
|
|
|
|
await Task.Delay(ExponentialBackoff[retryAttempt]).ConfigureAwait(false);
|
2019-10-10 17:19:28 +02:00
|
|
|
|
if (retryAttempt < ExponentialBackoff.Length - 1)
|
|
|
|
|
retryAttempt++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static async Task<T> Execute<T>(Func<Task<T>> callback)
|
|
|
|
|
{
|
|
|
|
|
var returnValue = default(T);
|
|
|
|
|
|
|
|
|
|
await Execute(async () =>
|
|
|
|
|
{
|
2024-04-08 14:20:15 +02:00
|
|
|
|
returnValue = await callback().ConfigureAwait(false);
|
|
|
|
|
}).ConfigureAwait(false);
|
2019-10-10 17:19:28 +02:00
|
|
|
|
|
2022-11-23 09:13:38 +01:00
|
|
|
|
return returnValue!;
|
2019-10-10 17:19:28 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|