Анализ отложенных операций и работа с ними

5 5

Важным показателем хорошей работы системы является отсутствие отложенных операций циклично уходящих на перевыполнение, в связи с ошибками в выполнение экземпляров асинхронных обработчиках, блоках схем задач или другими микро-сервисами. В статье описаны способы отслеживания и остановки таких отложенных операций.

В статье рассматривается работа с СУБД PostgrSQL, поэтому все примеры запросов актуальны для данной СУБД. Для MSSQL запрос будет отличаться.

В список отложенных операций попадают асинхронно выполняемые операции, которые по той или иной причине не смогли успешно завершиться. Чаще всего в список отложенных операций попадают экземпляры асинхронных обработчиков и процессов исполнения блоков схем задач.

Работа сервиса отложенных операций выполняется по следующему принципу:

  1. При возникновении ошибки сервис Directum RX отправляет сообщение сервису отложенных операций через очередь RabbitMQ;
  2. Сервис DelayedOperationsService сохраняет сообщение в хранилище отложенных операций;
  3. По наступлению времени или по запросу сервис DelayedOperatinsService получает сообщение с отложенной операцией из хранилища и возвращает в исходную очередь. Если операция уже неактуальна, то сервис удаляет сообщение;

Все отложенные операции временно хранятся в таблице базы данных sungero_system_delayedoperation.

Таблица содержит следующие поля:

  • id - id отложенной операции (первичный ключ таблицы);
  • operationid - id экземпляра (обычно это слово Instance / Block / Monitoring + id сущности (документа, задачи, задания, номер блока в схеме задачи и т.д., но оно может быть незаполненным);
  • hash - хеш операции;
  • message - Json представление класса DelayOperationMessage со свойствами: type, id, operation и time (формат данных bytea);
  • headers - системная информация;
  • time - время следующего выполнения.

Вся основная информация об отложенной операции хранится в поле message:

  • Номер итерации;
  • ID сущности, с которой возникла проблем (задача, задание, документ и т.д.);
  • Если проблема в схеме задачи, то дополнительно информация о номере блока и номер версии схемы задачи, а также о типе операции, которую не удалось выполнить, например "CompleteProcessMessage";
  • Если проблема в работе асинхронного обработчика, то дополнительная информация об аргументах переданных в асинхронный обработчик.
  • и т.д.

Так как тип данных в поле message - bytea (Бинарные данные), данные из этого поля нужно преобразовывать в читаемый вид.

Для этого нужно использовать следующую команду:

SELECT id, operationid, hash, "time", headers, encode(message::bytea, 'escape')
FROM public.sungero_system_delayedoperation
WHERE encode(message::bytea, 'escape') LIKE '%%'
ORDER BY id DESC LIMIT 1000
  • encode(message::bytea, 'escape') - позволит перевести данные в поле message в читаемый вид;
  • LIKE '%%' - позволит найти нужную нам отложенную операцию по включающему тексту, для этого между знаками '%' нужно ввести информацию, которая должна содержаться в отложенной операции (Например id документа, переданного аргументом в невыполненный асинхронный обработчик);
  • ORDER BY id DESC - для того, чтобы все новые отложенные операции были вверху списка;
  • LIMIT 1000 - выведет информацию о последней 1000 отложенных операций. (ВАЖНО! При использовании SQL запросов обязательно наличие оператора запроса LIMIT, особенно в продуктивной среде, иначе запрос может сильно нагрузить БД, вплоть до полного зависания).

Пример работы с таблицей отложенных операций

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

В таком случае у нас есть несколько вариантов решения проблемы:

  1. По выявленной ошибке доработать асинхронный обработчик и проблема решится после публикации;
  2. Если ситуация такая, что проблема не решится доработкой в АО, но при этом операцию можно остановить для всех экземпляров (допустим документ / задача старые и нужны только как архивные данные), то можно остановить запросы в очереди RabbitMQ;
  3. Если 2 пункт невозможно выполнить, т.к. есть и старые и новые документы / задачи, то тогда мы точечно можем остановить выполнение АО в отложенных операциях.

В случае с пунктом 3 придется удалять записи из таблицы. Такой вариант можно использовать в крайнем случае, т.к. удаление записей из БД нежелательно.

Контроль количества отложенных операций

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

SELECT count(*) FROM public.sungero_system_delayedoperation;

 

Если для мониторинга ошибок используется Grafana, то легко можно понять, какие ошибки идут в отложенные операции по синусоидам графика.

https://club.directum.ru/uploads/images/57636c0e-2407-48f9-b4b3-8362d8834e41.png

Желтая и зеленая линии на графике явно говорят о повторяющейся ошибке, в результате анализа которой, возможно, придется удалять записи этих операций из таблицы отложенных операций.

 

Сергей Беляков

Утверждение, что в поле message хранится текст ошибки, не корректно, т.к. это Json представление класса DelayOperationMessage со свойствами: type, id, operation и time.
После десериализации, в зависимости от type, это сообщение выполняется в соответствующем сервисе.

Пример для блока мониторинга, который выполняется в WorkflowBlockService:

"{"$type":"Sungero.Workflow.ProcessServiceAPI.Block.BlocksDelayedOperationMessage, 
Sungero.Workflow.ProcessServiceBlockAPI",
"InstanceId":134,
"BlockId":"110",
"Operation":"Deadline",
"ExecutionTime":"2022-11-28T14:52:50.2"}"

 

Юрий Янин

Про контроль количества отложенных операций: в "коробке" РХ 4.2 в поручениях есть блок "Мониторинг начала корректировки" со свойством "срок прекращения = 10000 дней", поэтому в отложенные операции попадают записи по всем задачам ActionItemExecutionTask, и после завершения задачи запись остается в отложенных операциях (поле Time при этом 2049-2050 год). Поэтому, например, у нашего клиента в этой таблице более 500тыс записей по этим поручениям, и это не является "плохим" показателем для отложенных операций, так задумано в "коробке". Поэтому предлагаю запрос указать примерно такой (кол-во отложенных операций с пустым временем или с временем менее 10 дней)

select count(1)
from Sungero_System_DelayedOperation 
where Time is null or Time < DATEADD(DAY, 10, GETDATE())

Андрей Кораблёв

Сергей, Очень ценное замечание, поправлю в статье, спасибо!

Андрей Кораблёв

Юрий, не встречал такого блока мониторинга в 4.1 и 4.3. К тому же не удалось воспроизвести срок прекращения равный 10000 дней, максимум 3 дня. Можете приложить скриншот?
Основная идея запроса поиска длительных отложенных операций в том, чтобы найти операции с большим количеством итераций, то есть явно больше 10 дней.
В Вашем случае лучше исключать подобные блоки мониторинга другим способом из общего запроса, например выделив общую часть из поля message и исключать из запроса эту часть.

Андрей Кораблёв: обновлено 28.11.2022 в 07:52
Юрий Янин

Андрей, в 4.1 кажется еще не было Корректировки поручений, а в 4.3 добавили схему V4 для ActionItemExecutionTask. Можете в 4.3 в среде разработки переключить на схему V3 - в ней должно быть видно этот блок и этот срок. По крайней мере в скаченных с partners исходных кодах "Исходные коды для DirectumRX 4.3.23.0.zip\DirectumRXbase.dat\source\Sungero.RecordManagement\Sungero.RecordManagement.Server\ActionItemExecutionTask\ActionItemExecutionTaskScheme.V3.xml" видно этот блок 110 и срок в нем в 10000 дней.

Авторизуйтесь, чтобы написать комментарий