Расширенная функциональность
07
Май
0

Повтор асинхронных операций

Когда Асинхронная служба получает ошибку, то в зависимости от ситуации может быть три исхода:

  • Окончательный сбой – задание потерпело неудачу и не может быть возобновлено.
  • Повторная попытка – задание будет приостановлено и будет предпринята попытка повторного запуска после некоторого промежутка времени.
  • Приостановка – задание будет приостановлено, пока не будет возобновлено вручную.

Вот примеры некоторых ошибок и реакция на них асинхронных заданий и БП:

Сценарий Async job Workflow Error code
Ошибка вызова в SDK: обнаружен бесконечный цикл Fail Fail 80044182
Ошибка вызова в SDK: организация отключена Retry Retry 8004A104 / 8004A107
Ошибка вызова в SDK: сервер занят Retry Retry 8004A001
Ошибка вызова в SDK: другое Fail Suspend
SQL exception Retry Retry 80040216
Системное БП поставлено на паузу N/A Suspend 80045017
Сетевая ошибка Retry Retry 80044306
Запись ассоциированная с БП не найдена N/A Suspend 80045031
Ответ по HTTP завершился с ошибкой HttpStatusCode.Unauthorized Suspend Suspend 80044306
Ответ по HTTP завершился ошибкой Retry Retry 80044306
InvalidPluginExecutionException Fail Fail 80040265
Другое Fail Fail

Как можно заметить поведение у БП и других асинхронных операций иногда различается. Это связано с тем, что зачастую фейл БП может исправить пользователь, ответственный за запись. Например, БП не может отправить письмо из-за отсутствия у получателя адреса электронной почты. Пользователь может добавить адрес электронной почты и возобновить БП. С другой стороны, асинхронные задания зачастую выполняются под системной учеткой и вряд ли кто-то будет исправлять причины индивидуальных сбоев.

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

Количество попыток задается в системном свойстве AsyncMaximumRetries. Интервал между этими повторениями определяется свойством AsyncRetryBackoffRate. При этому время ожидания каждого следующего повтора растет по экспоненте (для значений по умолчанию):

Повтор Ожидание (секунд)
0 36
1 43
2 52
3 62
4 75
>=5 Приостановлен

Если в Отложен до стоит значение 30.12.9999 23:59:59 (максимально возможное значение DateTime), то это означает что Системное задание должно быть возобновлено вручную.
Но что самое интересное – есть недокументированный и неподдерживаемый способ использовать механизм повторения заданий в кастомных шагах. Суть его в том, что нужно принудительно вызвать одно из исключений, которое приводит к повторному выполнению задания. Такой подход может помочь, чтобы попытаться автоматически исправить ошибки возникшие в процессе выполнения. Например, произвошла кратковременная сетевая ошибка, которая прервала интеграцию. В таком случае повторный запуск кода успешно ее завершит.

using System;
using System.Activities;
using Microsoft.Xrm.Sdk;

namespace ActivityLibrary1
{
    public sealed partial class Class1: CodeActivity
    {
        protected override void Execute(CodeActivityContext Execution)
        {
            try
            {
                var x = 0;
                var z = 1 / x;
            }
            catch (Exception ex)
            {
                // TODO: Rollback any non-transactional operations
                OrganizationServiceFault fault = new OrganizationServiceFault();
                fault.ErrorCode = -2147204346; // This will cause the Async Server to retry
                fault.Message = ex.ToString();
                var networkException = new System.ServiceModel.FaultException<OrganizationServiceFault>(fault);
                throw networkException;
            }
        }
    }
}

Учтите, что автоматический повтор не отменяет уже выполненных действий. И если Вы насоздавали записей, то повторный запуск создаст их снова. Поэтому любые откаты вы должны выполнять самостоятельно в ветке catch.


Комментарии (0)

*

code