Найти в Дзене

Движок для обслуживания настраиваемых бизнес-процессов

Оглавление

Привет, меня зовут Дмитрий Ульянов, я разработчик-эксперт в Gems development. Сегодня я вместе с вами загляну под капот одной из самых объёмных интеграций этого года и поделюсь лайфхаками масштабирования решения по отправке документов.

Это я ;)
Это я ;)

Наша команда разработки ZT team является держателем домена ГИСОГД, и задачи, прямо или косвенно относящиеся к этой теме, ложатся именно на нас. В начале года по инициативе product owner’а Натальи Федоровой к нам в бэклог попала задача по обеспечению интеграции региональных ГИСОГД на базе нашей системы Geometa с внешними федеральными системами в рамках построения цифровой вертикали.

Если вы не видели схему цифровой вертикали, то вот она
Если вы не видели схему цифровой вертикали, то вот она

За плечами нашей команды немалый опыт работы с ГИСОГД, чего только стоила практика выстраивания взаимодействия с федеральной системой ГИСОГД РФ в конце прошлого года. На первый взгляд может показаться, что «поженить» два сервиса – это задача в пару строчек кода, но всё не так просто

Для нас эта работа началась с передачи двух видов сведений (кому интересно, это про документы «Разрешение на строительство» и «Разрешение на ввод») в ИСУП (Информационную систему управления проектами) и ИС ГСН (Информационная система государственного строительного надзора). Но впереди нас ждут аналогичные работы по сотне документов. Это значит, что нам предстоит под каждый новый документ включаться всей командой и писать код. Выглядит непродуктивно. Хорошо, что PO поддержала нас и разрешила найти low-code или no-code решение. И раз уж вы читаете это, значит, у нас это получилось. Но обо всём по порядку.

Раз уж нам всё равно предстояло отправлять документы в шину внешней системы (в нашем случае в Интеграционную шину), то ещё на старте работ было принято решение максимально облегчить жизнь пользователя и максимально автоматизировать процесс. Согласитесь, зачем просить человека делать какие-то действия, например, нажимать кнопку для отправки, если этого можно не делать. Например, при передаче сведений о «Разрешении на строительство», если документ сформирован и согласован, система сама его и отправит.

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

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

  1. из документа получается ссылка на архив с согласованными файлами;
  2. по ссылке архив скачивается из файлового хранилища системы;
  3. из архива извлекается электронная форма документа в XML-формате;
  4. проверяется, что эта XML действительно электронная форма документа РС;
  5. из неё формируются сообщения в шину для ИСУП и ГСН соответственно;
  6. отправляется сообщение в ИСУП;
  7. отправляется сообщение в ГСН.

Такое решение позволяет достичь несколько преимуществ.

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

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

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

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

Как настроить переход от шага к шагу?

Здесь нам на помощь пришло функциональное программирование, в частности Result type. Сначала мы заставили систему возвращать результат «ОК», если шаг осуществлен успешно, а если что-то пошло не так, то «Fail». Чуть позже к стандартным «OK» и «Fail» мы прикрутили некий код того самого «хорошо» или «плохо». Таким образом, в зависимости от ответа и его кода в конфигурационном файле, мы настроили его маршрутизацию на следующий шаг, или в случае Fail, например, перенаправление на шаг с ожиданием или повторным выполнением одного из предыдущих шагов.

И, конечно же, мы не забыли про необходимость существования в нашем движке RetryPolicy. Понимаем, что всякое в жизни бывает. Например, если при отправке сообщения в шину у customer’a (заказчика, пользователя) разорвалось интернет-соединение, то наша система просто повторит отправку.

Обработчик для RetryPolicy мы сделали гибким и настраиваемым: позволили указывать число попыток, время между ними и даже параметры нарастания временного интервала между попытками, и даже указывать, куда переходить, если все попытки исчерпаны и надежды утрачены.

Заметим, что настраиваемость мы обеспечили не только для обработчика RetryPolicy, но и для других.

Пример использования RetryPolicy
Пример использования RetryPolicy

Как настроить обработчик так, чтобы его можно было по-разному использовать в разных процессах?

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

А что, если бизнес-процессы будут тяжелые? Что, если нужно обеспечить параллельность их выполнения, а не ждать очереди?

Наш сервис мы завернули в docker-образ, а конфигурационные файлы вынесли в тома (volume) наружу. Таким образом, если нам нужно обеспечить быструю работу каких-то тяжелых бизнес-процессов, мы можем решить это путём запуска разных процессов в независимо работающих docker-контейнерах. Да, это может быть ресурсоёмко в некоторых случаях, но это будет оправдано.

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

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

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

Мы обеспечили возможность выгрузки из Geometa не только данных документа, но и всего дерева связанных с ним объектов в XML-представление. Более того, для удобства пользователя и сокращения времени обмена данными добавили возможность запроса отдельных атрибутов документов (полей) или их групп.

Используя полученную XML и богатые возможности XSLT-преобразований, мы смогли сделать no-code’овым и аспект формирования электронных форм документов. Сейчас наш движок умеет запрашивать из Geometa XML и посредством использования XSLT-файлов преобразовывать исходную XML в необходимый формат электронной формы документа. Когда потребуется добавить обработку новых документов, достаточно внести правки в конфигурационных файлах модуля и настроить новые XSLT.

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