I'm trying to handle all 401 responses with an AsyncRetryPolicy.
Some notes:
Here's the retry policy:
var unauthorizedPolicy = Policy.Handle<ApiException>(ex => ex.StatusCode == HttpStatusCode.Unauthorized)
.RetryAsync(3, async (exception, retryCount) =>
{
Logger.Instance.Info($"Unauthorized, token probably expired, retry count: {retryCount}");
try
{
Logger.Instance.Error(exception.Message);
Logger.Instance.Info("Retrying request and retrive refresh token");
var token = await _authService.SignInSilentlyAsync();
await SecureStorage.SetAsync(Constants.PreferencesNames.Token.Value, token);
}
catch (Exception ex)
{
Logger.Instance.Error(ex.Message);
Logger.Instance.Info("SignInSilentlyAsync failed, going to login page");
NavigationService.ReplaceRoot(new LoginPageViewModel());
}
});
This is executed in another class:
result = await _taskManager._defaultPolicyForHttpRequests // the above defined unauthorizedPolicy
.ExecuteAndCaptureAsync<T>(async () => await task)
.ConfigureAwait(false);
Basically, when the token is expired I try and successfully get a new token but it seems that each attempt still uses the old one:
As you can see from the logs, the token is successfully retrieved, yet I think the old one is used when retrying the call. I cannot be sure because the call is no longer logged.
This brings me to my second question, is there any way to log and debug each HTTP call that Polly retries?
As you can see from the logs, the token is successfully retrieved, yet I think the old one is used when retrying the call. I cannot be sure because the call is no longer logged.
There is only one call being made by the code:
var task = SomeMethodNotShownAsync();
result = await _taskManager._defaultPolicyForHttpRequests // the above defined unauthorizedPolicy
.ExecuteAndCaptureAsync<T>(async () => await task)
.ConfigureAwait(false);
Particularly, this is the problematic part:
ExecuteAndCaptureAsync<T>(async () => await task)
await
does not "execute a task". It asynchronously waits for a task to complete. So the first time async () => await task
is executed by Polly, it asynchronously waits for the task to complete. It eventually completes with an error. All future executions of async () => await task
asynchronously wait for the same task to complete - that task is already completed with an error.
So the current code is having Polly retry "wait for the operation to complete". It's not retrying the operation itself.
To fix this behavior, have Polly retry the actual work each time instead of just retrying "wait for the operation to complete":
result = await _taskManager._defaultPolicyForHttpRequests // the above defined unauthorizedPolicy
.ExecuteAndCaptureAsync<T>(async () => await SomeMethodNotShownAsync())
.ConfigureAwait(false);
is there any way to log and debug each HTTP call that Polly retries?
It already is. :) The reason there were only log messages for one call was because there was only one call.