Как оповестить всех пользователей 1С при изменении данных на сервере?

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

При разработке чатов, систем информирования или механизмов оперативного обновления данных в 1С часто возникает задача: как сообщить всем подключенным пользователям (клиентским сеансам) о том, что на сервере произошло событие (например, записан документ, обновлен курс валют или пришел запрос через веб-сервис)?

Разберем, почему стандартные клиентские методы не работают для массовой рассылки с сервера, проанализируем ошибки и рассмотрим проверенные архитектурные решения этой задачи.

Причина проблемы: почему метод Оповестить() не работает для всех сеансов

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

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

Решение 1. Очередь событий в БД + Обработчик ожидания (Polling)

Это классический и универсальный способ, работающий на любых версиях платформы 1С:Предприятие 8.

Суть подходы заключается в следующем: при наступлении события на сервере запись о нем фиксируется в базе данных (например, в регистре сведений), а на клиенте периодически выполняется опрос (polling) этого регистра.

Рассмотрим реализацию по шагам:

  1. Фиксация события на сервере. В подписке на событие или бизнес-логике записываем факт изменения в регистр сведений ОчередьСобытий:

Процедура ПодпискаПриЗаписиПриЗаписи(Источник, Отказ, Замещение) Экспорт
    // Создаем запись в регистре сведений для оповещения пользователей
    МенеджерЗаписи = РегистрыСведений.ОчередьСобытий.СоздатьМенеджерЗаписи();
    МенеджерЗаписи.Период = ТекущаяУниверсальнаяДата();
    МенеджерЗаписи.ИмяСобытия = "ОбновлениеКурсов";
    МенеджерЗаписи.Параметр = "КурсыCurrencyОбновлены";
    МенеджерЗаписи.Записать();
КонецПроцедуры
  1. Подключение обработчика на клиенте. В модуле управляемого приложения или в форме подключаем периодическую проверку с помощью метода ПодключитьОбработчикОжидания():

Процедура ПриНачалеРаботыСистемы()
    ПодключитьОбработчикОжидания("ПроверитьНовыеСобытия", 10); // Проверка каждые 10 секунд
КонецПроцедуры

Процедура ПроверитьНовыеСобытия() Экспорт
    МассивСобытий = ПроверитьСобытияНаСервере();
    Для Каждого Событие Из МассивСобытий Цикл
        Оповестить(Событие.ИмяСобытия, Событие.Параметр);
    КонецЦикла;
КонецПроцедуры

Достоинства: Простая реализация, работающая на любых версиях платформы.
Недостатки: Создает дополнительную нагрузку на сервер БД при большом количестве активных пользователей.

Решение 2. Использование Системы взаимодействия (1С 8.3.10+)

Платформа 1С содержит встроенную Систему взаимодействия, которая позволяет организовывать обмены сообщениями и push-уведомлениями между сеансами без необходимости постоянных запросов к базе данных.

Проанализируем пример отправки сообщения с сервера:


// На сервере в подписке на событие создаем сообщение в обсуждении
Обсуждение = СистемаВзаимодействия.ПолучитьОбсуждение("ОбщийЧатОповещений");

Сообщение = СистемаВзаимодействия.СоздатьСообщение(Обсуждение.Идентификатор);
Сообщение.Текст = "Курсы валют успешно обновлены!";
Сообщение.Записать();

На клиенте можно подключить обработчик получения сообщений Системы взаимодействия. Клиентские сеансы будут получать информирование мгновенно в режиме реального времени.

Решение 3. Менеджер уведомлений клиента (1С 8.3.26+)

В современных версиях платформы добавлен специализированный механизм push-уведомлений — объект МенеджерУведомленийКлиента (доступен через УведомленияКлиента).

Этот механизм разработан специально для доставки произвольных событий с сервера напрямую на клиенты без использования Системы взаимодействия.

Посмотрим на пример отправки с сервера:


// На сервере отправляем событие всем подключенным сеансам
ДанныеУведомления = Новый Структура("Статус", "Обновлено");
УведомленияКлиента.ОтправитьУведомление("Чат_Обновление", ДанныеУведомления);

На стороне клиента подписываемся на перехват данного события:


Процедура ПриНачалеРаботыСистемы()
    УведомленияКлиента.ПодключитьОбработчик("Чат_Обновление", Новый ОписаниеОповещения("ОбработатьСерверноеСобытие", ЭтотОбъект));
КонецПроцедуры

Процедура ОбработатьСерверноеСобытие(ИмяСобытия, Данные, ДополнительныеПараметры) Экспорт
    // Выполняем обновление интерфейса или оповещение формы
    Оповестить("ОбновитьСообщения");
КонецПроцедуры

Решение 4. Внешние брокеры сообщений и WebSocket

Для высоконагруженных систем или задач с требованиями к мгновенной доставке (сотни и тысячи одновременно работающих пользователей) применяют интеграцию с внешними брокерами сообщений (RabbitMQ, Redis) или WebSocket-серверами.

  1. Сервер 1С при записи данных отправляет HTTP/TCP-запрос брокеру сообщений.
  2. Внешняя компонента Native API, подключенная на клиенте 1С, держит постоянное WebSocket-соединение с брокером.
  3. Брокер мгновенно пересылает событие всем подключенным клиентам.

Итоги

Выяснив ограничения метода Оповестить(), мы видим, что напрямую передать клиентское событие из серверной подписки всем сеансам нельзя. Выбор оптимального решения зависит от версии вашей платформы:

← На главную