61 lines
1.6 KiB
C#
61 lines
1.6 KiB
C#
using System;
|
|
using System.Data.SqlClient;
|
|
using System.Threading.Tasks;
|
|
|
|
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
|
|
{
|
|
await callback();
|
|
break;
|
|
}
|
|
catch (SqlException e)
|
|
{
|
|
if (SqlExceptionHelper.IsTransientError(e))
|
|
{
|
|
await Task.Delay(ExponentialBackoff[retryAttempt]);
|
|
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 () =>
|
|
{
|
|
returnValue = await callback();
|
|
});
|
|
|
|
return returnValue!;
|
|
}
|
|
}
|
|
}
|