Как стать автором
Обновить

Комментарии 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) до сих всплывает эта тема.

  • раздел блогов на сайте разработчиков фактически мертв, основной вектор публикаций теперь направлен сюда.

Касательно "залайканности" - видимо, пригодилось.

Ну вы б хоть код поправили, типизацию там, под современные реалии...

Все примеры кода поправлены здесь. А в исходной статье дана ссылка сюда.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий