Polly RetryAsyn c не работает и код не зарегистрирован - PullRequest
1 голос
/ 28 января 2020

Я пытаюсь обработать все 401 ответов с помощью AsyncRetryPolicy .

Некоторые примечания:

  • Я использую Xamarin.Forms
  • Я использую Установите , но без HttpClientFactory

Вот политика повторных попыток:

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());
        }
    });

Это выполняется в другом классе:

result = await _taskManager._defaultPolicyForHttpRequests // the above defined unauthorizedPolicy
    .ExecuteAndCaptureAsync<T>(async () => await task)
    .ConfigureAwait(false);

Обычно, когда срок действия токена истек, я пытаюсь и успешно получаю новый токен, но кажется, что каждая попытка все еще использует старый:

enter image description here

Как видно из журналов, токен успешно получен, но я думаю, что старый используется при повторной попытке вызова. Я не могу быть уверен, потому что вызов больше не регистрируется.

Это подводит меня ко второму вопросу, есть ли способ log и debug каждый HTTP-вызов, который Полли пытается?

1 Ответ

2 голосов
/ 28 января 2020

Как видно из журналов, токен успешно получен, но я думаю, что старый используется при повторной попытке вызова. Я не могу быть уверен, потому что звонок больше не регистрируется.

Код выполняется только один звонок:

var task = SomeMethodNotShownAsync();
result = await _taskManager._defaultPolicyForHttpRequests // the above defined unauthorizedPolicy
    .ExecuteAndCaptureAsync<T>(async () => await task)
    .ConfigureAwait(false);

В частности, это проблема c часть:

ExecuteAndCaptureAsync<T>(async () => await task)

await не не"выполнить задачу". Он асинхронно ожидает задания до завершения . Таким образом, в первый раз async () => await task выполняется Полли, она асинхронно ожидает завершения задачи. Это в конечном итоге завершается с ошибкой. Все будущие исполнения async () => await task ожидают асинхронного выполнения той же задачи - эта задача уже выполнена с ошибкой.

Таким образом, текущий код имеет Полли повторите попытку «дождитесь завершения операции». Сама операция не повторяется.

Чтобы исправить это поведение, попросите Полли каждый раз повторять фактическую работу вместо того, чтобы просто повторить «ожидание завершения операции»:

result = await _taskManager._defaultPolicyForHttpRequests // the above defined unauthorizedPolicy
    .ExecuteAndCaptureAsync<T>(async () => await SomeMethodNotShownAsync())
    .ConfigureAwait(false);

есть ли способ регистрировать и отлаживать каждый HTTP-вызов, который повторяет Полли?

Это уже есть. :) Причина, по которой были только сообщения журнала для одного вызова, была в том, что был только один вызов.

...