Привет, Хабр!
Меня зовут Михаил, я ведущий разработчик в НЛМК ИТ. Команда, в которой я состою, занимается разработкой и поддержкой различных информационных систем, одной из которых является Единый корпоративный портал ГК НЛМК на базе Битрикс24.
Когда спускаешься в метро, всё кажется простым: выбрать ветку, дождаться поезда, выйти на нужной станции. Но за этим привычным процессом кроется сложная система взаимосвязей: маршруты, расписания, отслеживание поездов, управление потоками пассажиров. Ошибка в любой из этих систем может вызвать хаос. В информационных системах крупных компаний всё устроено похоже.
Ранее мы уже начинали рассказывать о том, что для унификации и ускорения разработки отдельных сервисов, у нас активно применяется модуль бизнес-процессов Битрикса.
Как раз этот инструмент помогает нам превращать сложные и многоэтапные процессы в чёткую и понятную структуру. Бизнес-процессы помогают не только быстрее реализовать требуемую бизнес-логику для каждого конкретного случая за счет предоставления унифицированных интерфейсов, но и значительно упрощают поддержку сервисов. Наглядное представление бизнес-процессов, как карта метро, позволяет быстро понять жизненный цикл заявки, происходящие действия на каждом этапе ее обработки и при необходимости корректировать их. В первую очередь это важно для больших команд, когда сервис начинает разрабатываться одним разработчиком, дорабатываться вторым, поддерживаться третьим — издержки на ведение документации, передачу знаний и вникание в процессы значительно сокращаются.
Опираясь на наш опыт работы с этим инструментом, накопленные знания и часто встречающиеся вызовы, хочу поделиться некоторыми советами и нюансами работы с бизнес-процессами. Эта статья — путеводитель по "метро" корпоративных порталов: от автозапуска процессов до оптимизации сложной логики.
Нюансы автозапуска бизнес-процессов у заявок, формируемых в публичной части сайта
У битрикса при создании шаблонов бизнес-процессов для, например, инфоблоков, есть возможность активации автозапуска процесса при создании/изменении элементов через простановку одноименных флажков:
Но здесь зарыт неочевидный момент: штатные API-методы битрикса (напр. CIBlockElement::Add или \Bitrix\Iblock\ElementTable::add) автоматически не инициируют действия над бизнес-процессами. Указанные настройки действуют только при работе в пределах админки битрикса.
Если же объекты, участвующие в бизнес-процессах, создаются из публичной части через кастомные компоненты/контроллеры с использованием методов API - штатный автозапуск к ним не применится, и нужно стартовать бизнес-процессы вручную. В случае с инфоблоками в простейшем виде это может выглядеть так:
$iblockId = <id инфоблока>;
$arFields = [<поля элемента>];
\Bitrix\Main\Loader::IncludeModule('iblock');
\Bitrix\Main\Loader::IncludeModule('bizproc');
$element = new \CIBlockElement();
$id = $element->add($arFields);
if ($id) {
\CBPDocument::AutoStartWorkflows(
['iblock', 'CIBlockDocument', 'iblock_' . $iblockId),
\CBPDocumentEventType::Create,
['iblock', 'CIBlockDocument', $id],
[],
$arErrors
);
}
За кадром этого листинга остались отлов и обработка ошибок, возможная передача параметров в запускаемый бизнес-процесс. Все это уже должно подгоняться под частные случаи и подходы, применяемые в конкретном проекте и бизнес-процессе.
Кроме того, необходимо держать в уме, что по умолчанию элементы, участвующие в бизнес-процессе, являются не опубликованными, даже если флаг активности у них включен. Если на вашем фронте созданный элемент начинает использоваться сразу же (например, пользователь видит свою заявку в личном кабинете еще до согласования) — в бизнес-процессе необходимо добавить соответствующее действие:
Комбинирование классов и бизнес-процессов при создании сервисов
Сложные бизнес-процессы, содержащие дополнительную логику во вставках PHP-кода, имеют ряд сопутствующих проблем:
Код в этих вставках выпадает из системы контроля версий.
Сложность проведения ревью этого кода, особенно если объем логики большой.
Код во вставках не редактируется из любимого IDE, его сложно охватить целиком.
Но эти проблемы легко компенсировать, если построить вставку блоков кода при помощи заранее заготовленных хелперов, хранящихся в общей кодовой базе.
Например, это можно сделать так:
class BizProcTpl10
{
public static function statusStartEnter(\CBPActivity &$activity): void
{
// Логика на входе в статус Старт
}
// Прочие методы
public static function statusClosedEnd(\CBPActivity &$activity): void
{
// Логика в конце статуса Закрыта
}
}
В таких вставках PHP-кода будет только вызов соответствующего метода хелпера с передачей текущей активности:
BizProcTpl10::statusStartBegin($this->GetRootActivity());
Таким образом, все дополнительные вставки кода оказываются в репозитории системы контроля версий, доступны для проведения ревью и удобно редактируются из IDE.
Если бизнес-процесс изначально задумывается расширяемым или пишется в рамках гибкой методологии с постепенным добавлением функционала, может иметь смысл во всех статусах (или по крайней мере в тех, которые будут дорабатываться) на входе и на выходе заранее расставить по вставке PHP-кода с соответствующим методом хелпера. Такие заранее заготовленные вставки покрывают львиную долю кейсов, когда они могут потребоваться, и сокращают количество миграций по изменению бизнес-процесса. Также они могут служить аналогами перехвата событий движения по бизнес-процессу для более тонкого управления им.
Как не пропустить изменение элемента, если бизнес-процесс находится на паузе?
У заявок (и не только) могут быть ситуации, когда связанный с элементом бизнес-процесс встанет на паузу в ожидании определенного времени.
Например, нам требуется разработать сервис обработки заявок на участие в мероприятии. Согласно бизнес-процессу, после окончания мероприятия его статус должен измениться на "Мероприятие завершено" и запустить следующую за этим цепочку событий (допустим, получение обратной связи, подтверждение участия и т.п.). Очевидным решением для этого процесса будет использование действия "Пауза в выполнении" до даты окончания мероприятия, на которое подана заявка. Этот механизм работает таким образом, что битрикс создает агент, возобновляющий бизнес-процесс в указанную в параметрах паузы дату.
Но в жизни может случиться всякое — мероприятие может быть перенесено или отменено. Созданный при постановке на паузу агент от этого не изменится и так и будет ожидать времени, которое было задано в момент постановки бизнес-процесса на паузу. Соответственно, если в расписании произойдут изменения, он активируется совсем не тогда, когда хотелось бы.
Решить эту проблему можно двумя путями — со стороны кода и непосредственно в бизнес-процессе.
Через код можно повесить перехватчик события на изменение элементов инфоблока мероприятий, проверять в нем наличие ожидающих бизнес-процессов заявок и менять их вручную (путем изменения даты агента или действиями над бизнес-процессом). Но такое решение сразу лишает бизнес-процесс его основного преимущества — наглядности. Из редактора разработчик никак не увидит, что процесс может меняться из перехватчика события.
Чтобы не терять суть бизнес-процесса и сохранить всю логику внутри него, можно реализовать схему из цикла множества ожиданий, которые будут повторяться до тех пор, пока событие не наступит. Например:
На этой схеме мы видим цикл, в начале которого происходит актуализация текущего времени окончания мероприятия с сохранением его в переменную бизнес-процесса (этого может и не быть, если бизнес-процесс зависит от даты, хранимой в свойстве элемента, для которого запущен процесс), и условия, завершилось ли мероприятие, которое может выглядеть таким образом:
Если мероприятие завершено — происходит выход из цикла и бизнес-процесс продолжается, а если нет — устанавливается пауза на некоторое время. В зависимости от критичности, срочности и потенциального количества пользователей, возобновления бизнес-процесса время паузы может быть выбрано любое, но слишком малое устанавливать не желательно, т.к. каждый бизнес-процесс создает отдельный агент, и их частое повторение может вызвать повышенную нагрузку на сервер.
Вообще, применимость такого подхода зависит от масштабов — какое планируется количество одновременно стоящих на паузе бизнес-процессов. При сотнях и тысячах такое количество ожидающих агентов не создадут заметной нагрузки на сервер. Десятки тысяч тоже имеют право на жизнь, если не ставить слишком малую паузу. В случае с сотнями тысяч одновременно ожидающих бизнес-процессов придется либо ставить значительную паузу в выполнении, либо искать иной подход.
Мастерство параллелизма
Для ветвления бизнес-процессов на несколько идущих друг с другом веток у битрикса есть две конструкции:
Параллельное выполнение;
Параллельное ожидание действия.
Параллельное выполнение предназначено для одновременного выполнения всех веток (если точнее — последовательно слева направо с переходом к следующей ветке, когда предыдущая завершается, ставится на паузу или ожидает действия). Выход из конструкции происходит только после того, как каждая из веток дойдет до конца. Каких-либо ограничений на содержимое веток нет — вы можете устанавливать абсолютно любые действия в любом порядке.
Параллельное ожидание действия, в свою очередь, требует обязательной установки в начале каждой ветки команды, задания, или паузы, т.е. действий, ожидающих события. Выполнена будет только та ветка, действие в которой совершится первым, а задачи в других автоматически снимаются.
Эти конструкции покрывают значительное число базовых кейсов с параллельными событиями, но все же могут встречаться ситуации, когда работать с ними приходится нестандартно. В первую очередь это касается параллельного ожидания действия, которой, в силу специфики (обязательное начало веток с задачи/команды/паузы), сильно недостает гибкости, когда в каждой из веток нужно пройти предварительно некоторое количество шагов до непосредственного действия, но при этом выполниться в конечном счете должна будет только одна ветка, не дожидаясь завершения других, как в параллельном выполнении.
Для всех таких нетиповых ситуаций можно использовать конструкцию параллельного выполнения, из которой, как из пластилина, можно вылепить абсолютно любую логику.
Вернемся к ранее поднятому примеру с заявкой, ожидающей завершения мероприятия. Предположим, что также необходимо предоставить возможность пользователю отменить заявку в любой момент до окончания события. Соответственно, бизнес-процесс должен либо дождаться на паузе завершение мероприятия, либо пользователь выполнит задачу по отмене заявки (это словосочетание может резать слух, но в рамках бизнес-процессов технически отмена заявки представляет собой именно задачу, которую пользователь либо успеет выполнить до завершения процесса, прервав его, либо нет).
На ум сразу приходит параллельное ожидание действия. Но если у нас нет возможности указать фиксированное время для паузы, то применить такую конструкцию мы, увы, не сможем, битрикс просто не даст сохранить бизнес-процесс. И это правильно, поскольку суть конструкции в том, что если ветка ожидающего действия начата — другие мгновенно закрываются. Вместо ожидания действия здесь можно применить параллельное выполнение, в котором в каждой ветке будет одновременно выполняться определенная логика, которая в случае более раннего завершения схлопнет всю конструкцию целиком, прервав остальные ветки, при помощи действия "Установить статус". Для нашего примера это будет выглядеть таким образом:
По своей сути параллельное выполнение на этой схеме абсолютно равнозначно параллельному ожиданию действия, но в первой ветке с нефиксированной паузой мы смогли расположить конструкцию с циклом, которая была бы просто не доступна в ожидании действия.
За счет действия по изменению статуса бизнес-процесса, та ветка, которая завершится раньше - автоматически прервет остальные ветки, как и в параллельном ожидании действия.
Это не единственный случай, когда может понадобиться такой механизм. Ветки могут прерывать конструкцию и раньше, или же дождаться выполнения только части веток, прервав другие - все зависит от потребностей бизнеса и фантазии разработчика.
Заключение
В заключение хотелось бы подчеркнуть, что использование бизнес-процессов в 1С-Битрикс предоставляет разработчикам мощный инструмент для реализации сложных логических операций в рамках корпоративных порталов. При грамотном подходе можно значительно упростить и ускорить разработку, поддерживать порядок в кодовой базе, а также обеспечивать прозрачность и управляемость для всех участников процесса.
Автоматизация с использованием бизнес-процессов позволяет избежать многих потенциальных ошибок и упрощает взаимодействие между различными отделами и командами. Это особенно актуально для крупных корпораций, где количество участников проекта, возможно, исчисляется десятками или сотнями, и каждое изменение должно быть четко регламентировано и отслежено.
Надеемся, что представленные советы и подходы будут полезны вам в работе и поспособствуют более эффективному и продуманному построению бизнес-логики в ваших проектах. Спасибо за внимание, до встречи в следующих статьях!