Что такое СерверныеОбработчики в БСП и как устроен механизм служебных событий?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При изучении и доработке конфигураций на базе Библиотеки стандартных подсистем (БСП) разработчики нередко сталкиваются с кодом регистрации различных модулей в коллекциях КлиентскиеОбработчики и СерверныеОбработчики. На первый взгляд такой синтаксис вызывает вопросы: откуда берутся эти переменные, где они инициализируются и как платформа 1С их обрабатывает. Разберем детально архитектуру этого механизма, выясним причину его появления и научимся правильно объявлять свои обработчики.

Назначение механизма служебных событий в БСП

В платформе 1С:Предприятие штатный механизм подписок на события жестко привязан к объектам метаданных — справочникам, документам, планам обмена или процессам записи. Однако для создания модульной архитектуры конфигурации часто требуется шина абстрактных программных событий. Например, подсистема обновления метаданных или подсистема вариантов отчетов должна уведомить другие независимые подсистемы о наступлении определенного этапа работы.

Чтобы избежать жестких циклических связей между модулями и обеспечить возможность выборочного внедрения подсистем БСП, разработчики библиотеки реализовали собственную событийную модель:

  1. Подсистема-источник объявляет событие (точку расширения), задавая строковый идентификатор вида "ИмяПодсистемы\ИмяСобытия".
  2. Подсистемы-потребители регистрируют имена своих служебных модулей в переданных коллекциях обработчиков.
  3. Ядро БСП в нужный момент времени динамически обращается к зарегистрированным модулям и выполняет в них экспортные процедуры с соответствующими именами.

Где и как формируется коллекция СерверныеОбработчики

Посмотрим на пример кода, с которого начинается подключение обработчиков внутри служебного модуля подсистемы:


СерверныеОбработчики["СтандартныеПодсистемы.БазоваяФункциональность\ПриДобавленииПереименованийОбъектовМетаданных"].Добавить(
    "АнализЖурналаРегистрацииСлужебный");

Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ВариантыОтчетов") Тогда
    СерверныеОбработчики["СтандартныеПодсистемы.ВариантыОтчетов\ПриНастройкеВариантовОтчетов"].Добавить(
        "АнализЖурналаРегистрацииСлужебный");
КонецЕсли;

Параметр СерверныеОбработчики представляет собой универсальную коллекцию — Соответствие. Ключом данного соответствия выступает строка пути к событию, а значением — Массив строк с именами общих модулей, которые вызываются при наступлении события.

Проанализируем, где именно рождается эта коллекция. Инициализация выполняется ядром БСП в общем модуле СтандартныеПодсистемыСервер внутри экспортной функции ОбработчикиСобытий:


// Фрагмент механизма сбора обработчиков в СтандартныеПодсистемыСервер
Если Описание.ДобавлятьОбработчикиСлужебныхСобытий Тогда
    Модуль.ПриДобавленииОбработчиковСлужебныхСобытий(
        ОбработчикиКлиентскихСлужебныхСобытийПоПодсистемам[Подсистема],
        ОбработчикиСерверныхСлужебныхСобытийПоПодсистемам[Подсистема]
    );
КонецЕсли;

Таким образом, коллекция передается во входной параметр экспортной процедуры ПриДобавленииОбработчиковСлужебныхСобытий(КлиентскиеОбработчики, СерверныеОбработчики) каждого служебного модуля подсистем конфигурации.

Внутреннее хранение и кэширование реестра

Разберем по шагам, как БСП оптимизирует вызовы и почему постоянный опрос модулей не замедляет работу всей системы:

  1. Сериализация в константу: Реестр всех обработчиков не компилируется при каждом старте сеанса заново. При первом запуске или обновлении информационной базы дерево связей сериализуется в системную константу ПараметрыСлужебныхСобытий (хранилище значений).
  2. Кэширование на сервере: Во время пользовательского сеанса данные считываются с помощью общего модуля с повторным использованием возвращаемых значений (например, СтандартныеПодсистемыПовтИсп). Это исключает повторные обращения к базе данных при многократных вызовах событий.
  3. Динамический вызов: При возникновении события ядро БСП берет из кэша список модулей и с помощью конструкции вызова процедур по имени запускает целевой алгоритм в модуле-обработчике.

Типичные ошибки при работе с обработчиками событий

Рассмотрим распространенные проблемы, возникающие при внедрении собственных событий или изменении стандартных модулей БСП:

  1. Рассинхронизация кэша служебных событий: Вы добавили процедуру ПриДобавленииОбработчиковСлужебныхСобытий или зарегистрировали новый модуль, но программа выдает ошибку о том, что параметр служебных событий не заполнен или событие не найдено. Причина заключается в том, что константа ПараметрыСлужебныхСобытий хранит старую структуру.
  2. Отсутствие проверки подсистем: Если модуль регистрирует обработчик для события подсистемы, которая была удалена или отключена, возникнет исключение при попытке доступа к несуществующему ключу соответствия.
  3. Несовпадение имен и параметров: Так как связь между событием и модулем формируется через строковые литералы, синтаксический контроль платформы 1С не сможет отследить опечатку в названии общего модуля или сигнатуре процедуры. Ошибка проявится только непосредственно в момент вызова события.

Способы устранения ошибок и рекомендации

Выясним, какие действия необходимо предпринять для корректной работы служебных обработчиков:

  1. Запуск обновления информационной базы: Для пересчета кэша запустите клиент 1С с параметром командной строки /C ЗапуститьОбновлениеИнформационнойБазы либо вызовите в коде ОбновлениеИнформационнойБазы.ВыполнитьОбновлениеИнформационнойБазы(). Это инициирует перезапись константы служебных событий.
  2. Безопасное добавление обработчиков: Всегда проверяйте доступность подсистемы-источника перед обращением к коллекции:
    
    Если ОбщегоНазначения.ПодсистемаСуществует("ИмяПодсистемы") Тогда
        СерверныеОбработчики["ИмяПодсистемы\ИмяСобытия"].Добавить("МойСлужебныйМодуль");
    КонецЕсли;
    
  3. Учет версий БСП: Обратите внимание, что в современных версиях БСП (редакции 3.x) архитекторы 1С постепенно отказались от тяжеловесной константы ПараметрыСлужебныхСобытий в пользу переопределяемых модулей (например, ОбщегоНазначенияПереопределяемый) и механизма расширений, что упрощает поиск ссылок и статическую проверку конфигурации.
← На главную