Комментарии 1
Ваши коллеги по цеху придумали другое решение, которое является более самостоятельной и переиспользуемой версией "флага защиты от рекурсии" - реализация интерфейсаBitrix\HumanResources\Contract\Service\SemaphoreService
. По сути, этот сервис предоставляет средства консультативной блокировки, который держит все блокировки в памяти.
Использование выглядит примерно так:
<?php
use Bitrix\HumanResources\Service\Container;
function handleUpdate(): void {
$semaphoreService = Container::getSemaphoreService();
if ($semaphoreService->isLocked('UNIQUE_LOCK_NAME')) {
return;
}
$semaphoreService->lock('UNIQUE_LOCK_NAME');
// ... do recursive stuff ...
$semaphoreService->unlock('UNIQUE_LOCK_NAME');
}
Помимо того, что с помощью SemaphoreService
можно гораздо явнее обозначить защиту от рекурсии, вы также избавляете себя от нескольких головных болей:
Решение единообразное и может быть переиспользовано в нескольких проектах, в отличие от необходимости каждый раз внедрять статическое поле в класс, который может столкнуться с проблемами рекурсии;
Нет необходимости предоставлять публичное API внутри вашего класса. Те разработчики, которые хотят управлять этим поведением извне, будут использовать
SemaphoreService
, а не API вашего класса; вы, таким образом, снимаете с себя (а именно, со своего класса) ответственность, всё "неожиданное" поведение оказывается виной того, кто нарушил инкапсуляцию вашего обработчика.
Странно, что подобного сервиса всё ещё нет в главном модуле.
Как избавиться от зацикливания обработчиков событий в Битриксе