У меня есть консольное приложение dotnet core (2.1), и я использую Polly, чтобы обернуть сегмент моего кода с помощью политики повторных попыток.Это прекрасно работает с простым примером использования, показанным ниже:
private void ProcessRun()
{
var policy = Policy.Handle<SocketException>().WaitAndRetryAsync(
retryCount: 3
sleepDurationProvider: attempt => TimeSpan.FromSeconds(10),
onRetry: (exception, calculatedWaitDuration) =>
{
Console.WriteLine($"Retry policy executed for type SocketException");
});
try
{
CancellationTokenSource _cts = new CancellationTokenSource()
PollyRetryWaitPolicy.ExecuteAsync(async token => {
MyOperation(token);
}, _cts.Token)
.ContinueWith(p => {
if (p.IsFaulted || p.Status == TaskStatus.Canceled)
{
Console.WriteLine("faulted or was cancelled");
}
})
.ConfigureAwait(false);
}
catch (Exception ex) {
Console.WriteLine($"Exception has occurred: {ex.Message}");
}
}
Затем я проверяю его, используя этот код:
private void MyOperation()
{
Thread.Sleep(2000);
throw new SocketException();
}
Когда код выполняется, исключение сокета перехватывается, как и ожидалось,
Я искал свой гибкий способ обернуть мой код несколькими политиками вместо одной.Я изменил код, чтобы динамически добавлять несколько обернутых политик Polly Retry вместе, чтобы можно было перехватывать более одного типа ошибок и легко изменять исключения, которые я ищу.Я изменил код на следующий:
internal PolicyWrap PollyRetryWaitPolicy;
public void AddRetryWaitPolicy<T>(int waitTimeInSeconds, int retryAttempts)
where T: Exception
{
// Setup the polly policy that will be added to the executing code.
var policy = Policy.Handle<T>().WaitAndRetryAsync(
retryCount: retryAttempts,
sleepDurationProvider: attempt => TimeSpan.FromSeconds(waitTimeInSeconds),
onRetry: (exception, calculatedWaitDuration) =>
{
Console.WriteLine($"Retry policy executed for type {typeof(T).Name}");
});
if (host.PollyRetryWaitPolicy == null)
{
// NOTE: Only add this timeout policy as it seems to need at least one
// policy before it can wrap! (suppose that makes sense).
var timeoutPolicy = Policy
.TimeoutAsync(TimeSpan.FromSeconds(waitTimeInSeconds), TimeoutStrategy.Pessimistic);
PollyRetryWaitPolicy = policy.WrapAsync(timeoutPolicy);
}
else
{
PollyRetryWaitPolicy.WrapAsync(policy);
}
}
private void ProcessRun()
{
AddRetryWaitPolicy<SocketException>(10, 5);
AddRetryWaitPolicy<InvalidOperationException>(5, 2);
try
{
Console.WriteLine($"Calling HostedProcess.Run() method. AwaitResult: {awaitResult}");
CancellationTokenSource _cts = new CancellationTokenSource()
PollyRetryWaitPolicy.ExecuteAsync(async token => {
MyOperation(token);
}, _cts.Token)
.ContinueWith(p => {
if (p.IsFaulted || p.Status == TaskStatus.Canceled)
{
Console.WriteLine("Process has faulted or was cancelled");
}
})
.ConfigureAwait(false);
}
catch (Exception ex) {
Console.WriteLine($"Exception has occurred: {ex.Message}");
}
}
Когда я тестирую с этим кодом, приведенный выше код работает как ожидалось и повторяется 5 раз.
private void MyOperation()
{
Thread.Sleep(2000);
throw new SocketException();
}
НО, когда я пытаюсь сдалее он не повторяется 2 раза, как ожидалось (он не повторяется вообще):
private void MyOperation()
{
Thread.Sleep(2000);
throw new InvalidOperationException();
}
Что я делаю не так?Смысл всего вышеперечисленного заключается в динамическом множествении политик, как мне требуется.Есть ли лучший способ сделать что-то кроме WrapPolicy?
Спасибо за указатели заранее!