Комментарии 6
Ваши коллеги по цеху придумали другое решение, которое является более самостоятельной и переиспользуемой версией "флага защиты от рекурсии" - реализация интерфейса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 вашего класса; вы, таким образом, снимаете с себя (а именно, со своего класса) ответственность, всё "неожиданное" поведение оказывается виной того, кто нарушил инкапсуляцию вашего обработчика.
Странно, что подобного сервиса всё ещё нет в главном модуле.
спасибо за идею, но зачем в ядро ?private static array $handlerDisallow = [];
public static function disableHandler($UNIQUE_LOCK_NAME)
{
self::$handlerDisallow[$UNIQUE_LOCK_NAME]--;
}
public static function enableHandler($UNIQUE_LOCK_NAME)
{
self::$handlerDisallow[$UNIQUE_LOCK_NAME]++;
}
public static function isEnabledHandler($UNIQUE_LOCK_NAME)
{
if(!isset(self::$handlerDisallow[$UNIQUE_LOCK_NAME]))
self::$handlerDisallow[$UNIQUE_LOCK_NAME] = 0;
return (self::$handlerDisallow[$UNIQUE_LOCK_NAME] >= 0);
}
Извиняюсь за задержку с ответом - релиз.
Странно, что подобного сервиса всё ещё нет в главном модуле
Авторам класса передал, очень удивились, так как писали строго под свои нужды. Обещали подумать над переносом в main.
Помимо того, что с помощью
SemaphoreService
можно гораздо явнее обозначить защиту от рекурсии, вы также избавляете себя от нескольких головных болей
Согласен, но только после того, как такой механизм появится в main. Модуль humanresources (где сейчас лежит реализация) отсутствует в БУС (а необходимость возникает чаще всего именно там).
Коллеги, а поясните ценность статьи и ее "залайканность", с учетом того, что это почти полная копия статьи с вашего же сайта от 2014 года?
См. https://dev.1c-bitrix.ru/community/blogs/vws/looping-event-handlers.php
Ну вы б хоть код поправили, типизацию там, под современные реалии...
Коллеги, а поясните ценность статьи и ее "залайканность"
Да, это доработанный вариант старой статьи. Решено былло опубликовать его здесь, так как:
несмотря на "солидный возраст" оригинальной публикации, в профильных чатах (Telegram) до сих всплывает эта тема.
раздел блогов на сайте разработчиков фактически мертв, основной вектор публикаций теперь направлен сюда.
Касательно "залайканности" - видимо, пригодилось.
Ну вы б хоть код поправили, типизацию там, под современные реалии...
Все примеры кода поправлены здесь. А в исходной статье дана ссылка сюда.
Как избавиться от зацикливания обработчиков событий в Битриксе