I'm trying to implement a Retry/Timeout procedure to access a webservice, with Polly and Refit.
I have a timeout policy of 10 seconds (Polly.Timeout.TimeoutRejectedException on timeout)
.
I have a retry policy of 2 attempts.
I have a userCancellationToken
than can be canceled by the user.
If I don't set a Polly timeout policy, the client default timeouts after 100s with a System.IO.IOException
While this code basically works, I have some questions:
1) Is my code mostly correct?
2) If my timeout is at 10s, and I force my server to answer in 15s, as a timeout test, this code correctly does 3 attempts of 10s each and then fails, but after a few seconds I get displayed 3 "Success after...", meaning that the task was still running and waiting for data, even if Polly canceled it. How can I cancel the running task(s)?
3) If my server is unreachable I get a System.Net.Sockets.SocketException
after 4 seconds. How can I reduce this timeout?
var timeOutPolicy = Policy
.TimeoutAsync(
10,
TimeoutStrategy.Pessimistic);
var retryPolicy = Policy
.Handle<Exception>()
.RetryAsync(2, (exception, attempt) =>
{
sw.Stop();
progress.Report($"Error after {sw.Elapsed}");
progress.Report($"New attempt {attempt}");
if (exception.InnerException is System.Net.Sockets.SocketException)
{
progress.Report("Catched: SocketException (No server running or not reachable)");
}
if (exception.InnerException is System.IO.IOException)
{
progress.Report("Catched: IOException (normal timeout)");
}
if (exception is Polly.Timeout.TimeoutRejectedException)
{
progress.Report("Catched: Polly Exception (timeout set by Polly)");
}
if (exception.InnerException is ApiException) progress.Report("Catched: ApiException");
});
var policyWrap = Policy.WrapAsync(retryPolicy, timeOutPolicy);
try
{
await policyWrap.ExecuteAsync(async (ct) =>
{
sw.Restart();
progress.Report("Execute");
var api = RestService.For<ICTServerApi>("http://localhost:3105/json/reply/ReqUtenti");
respUtenti = await api.GetUtentiAsync(reqUtenti, userCancellationToken).ConfigureAwait(false);
sw.Stop();
progress.Report($"Success after {sw.Elapsed}");
}, userCancellationToken).ConfigureAwait(false);
}
Thanks!