Механизм повторной попытки ловли исключения не будет работать - PullRequest
0 голосов
/ 24 апреля 2020

Я реализую механизм повтора для вызова API, чтобы выполнить тот же запрос, если произошла заявленная бизнес-логика c. На данный момент я сделал это очень просто и улучшу его позже с помощью обработки exceptionType et c. Я просто выбрасываю исключение, если происходит логика c, и перехватываю их в механизме повтора, но ниже код просто убивает поток и не выполняется после первой попытки. Не могли бы вы помочь мне, пожалуйста, что мне здесь не хватает?

Это логи повторных попыток c Я пытаюсь использовать.

    public static T Do<T>(Func<T> action, TimeSpan retryInterval, int attemptCount)
    {
        var exceptions = new List<Exception>();

        for (int attempted = 0; attempted < attemptCount; attempted++)
        {
            try
            {
                if (attempted > 0)
                {
                    Thread.Sleep(retryInterval);
                }
                return action();
            }
            catch (Exception ex)
            {
                exceptions.Add(ex);
            }
        }
        throw new AggregateException(exceptions);
    }

Вот так я вызываю метод повторных попыток.

    await Task.Run(() =>
                {
                    RetryHelper.Do(() => ConfirmRequestRetryAsync(request, true), TimeSpan.FromSeconds(60), 10);
                });

И этот метод может генерировать исключения из-за логики c.

    public async void ConfirmRequestRetryAsync(ConfirmRequest request, bool flag)
    {
        logger.Info($"Confirm Request Async Called for the request : {JsonConvert.SerializeObject(request)}");
        var confirmRequest = GetSignedConfirmRequest(request.PaymentId);
        var confirmResponse = await MakeRequest(confirmRequest);
        //Added flag and sending at false at first try to not throw exception
        //Then in retry mechanism this exceptions will be use to trigger retry logic.
        if (flag)
        {
            var statu = ConfirmResponseXmlConvert(confirmResponse);
            if (statu.Item1 == "0" && statu.Item2 == "InProcess")
            {
                throw new Exception("InProcess");
            }
            else if (statu.Item1 == "-1" && statu.Item2 != "Declined")
            {
                throw new Exception("Error");
            }
        }
    }

1 Ответ

0 голосов
/ 24 апреля 2020

ConfirmRequestRetryAsync является асинхронным c пустым методом. Это означает, что он вернется с первого ожидания. Остальная часть кода будет выполняться позже, в том же контексте потока, что и вызывающая сторона. Поэтому, когда генерируются исключения, метод повторной попытки уже вернулся, и нет ничего, чтобы перехватить исключения.

Исправление состоит в том, чтобы сделать его асинхронным c методом Task, и ожидать этого в вашем методе retry. Для этого может потребоваться два варианта метода повторных попыток: один для асинхронных c методов и один для не асинхронных c.

Практическое правило для asyn c void - никогда не разрешать выбрасывать из них исключения, поскольку никто не может их перехватить. Всегда используйте asyn c Task, если возможны исключения.

...