В практике разработки на платформе 1С часто возникает задача: один пользователь вносит изменения в базу данных (например, создает запись в Регистре сведений), а другой пользователь должен мгновенно получить об этом уведомление. Традиционный подход с использованием обработчика ожидания часто вызывает вопросы из-за потенциальной нагрузки на сервер и клиентское приложение, особенно при работе через веб-клиент. Разберем наиболее эффективные способы решения этой задачи для платформы 8.3.12 и выше.
Прежде всего, важно понимать ограничение встроенных механизмов оповещения. Метод Оповестить() и обработчик ОбработкаОповещения работают исключительно в рамках текущего клиентского сеанса. Если пользователь А вызывает этот метод, пользователь Б об этом не узнает, так как их сессии изолированы друг от друга. Проанализируем ситуацию: нам нужен механизм, который позволит серверу «протолкнуть» (push) информацию клиенту или заставит клиента максимально эффективно проверять наличие обновлений.
Для платформы версии 8.3.10 и выше самым правильным решением является использование Системы взаимодействия. Это встроенный механизм, который позволяет пользователям и приложениям обмениваться сообщениями в реальном времени. Главное преимущество этого метода для веб-клиента — использование технологии WebSocket, которая держит открытым одно соединение и мгновенно передает данные без постоянных повторных запросов к серверу.
Рассмотрим по шагам, как настроить программную отправку уведомления. Сначала нам необходимо отправить сообщение при записи в регистр. Для этого в модуле набора записей регистра или в обработке, создающей запись, пропишем следующий код:
// На стороне отправителя (Пользователь 1)
Участники = Новый Массив;
Участники.Добавить(НужныйПользовательСсылка); // Ссылка на пользователя-получателя
Обсуждение = СистемаВзаимодействия.СоздатьОбсуждение();
Обсуждение.Ключ = "УведомлениеОНовойЗаписи";
Обсуждение.Участники = Участники;
Обсуждение.Записать();
НовоеСообщение = СистемаВзаимодействия.СоздатьСообщение(Обсуждение.Идентификатор);
НовоеСообщение.Текст = "В регистре появилась новая запись!";
НовоеСообщение.Записать();
Теперь разберем, как принять это сообщение на стороне получателя. В модуле управляемого приложения или в коде формы, которая должна реагировать, необходимо подключить обработчик события ПриПолученииСообщения. Посмотрим на пример реализации:
// На стороне получателя (Пользователь 2)
Процедура ПриНачалеРаботыСистемы()
СистемаВзаимодействия.ПодключитьОбработчикПриПолученииСообщения(
Новый ОписаниеОповещения("ОбработкаНовогоСообщения", ЭтотОбъект)
);
КонецПроцедуры
Процедура ОбработкаНовогоСообщения(Сообщение, ДополнительныеПараметры) Экспорт
Если Сообщение.Обсуждение.Ключ = "УведомлениеОНовойЗаписи" Тогда
ПоказатьОповещениеПользователя("Внимание!", , Сообщение.Текст);
// Здесь можно вызвать обновление формы или открыть окно
КонецЕсли;
КонецПроцедуры
Если внедрение Системы взаимодействия по каким-то причинам невозможно (например, нет возможности установить сервер взаимодействия), нам придется вернуться к методу ПодключаемыйОбработчикОжидания. Однако, чтобы он не стал «тяжелым» и не тормозил систему, его нужно реализовать максимально легко. Выясним причину нагрузки: чаще всего она возникает из-за того, что каждые несколько секунд выполняется сложный запрос к большой таблице регистра.
Проанализируем стратегию оптимизации: вместо опроса всего регистра мы будем проверять один-единственный «флаг» или дату последнего изменения. Рассмотрим алгоритм:
ДатаПоследнегоОбновления.Посмотрим на пример реализации «легкой» проверки:
// В форме на клиенте
Перем ПоследняяДатаПроверки;
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ПоследняяДатаПроверки = ТекущаяДатаСеанса();
ПодключитьОбработчикОжидания("ПроверитьОбновленияРегистра", 5); // Проверка каждые 5 секунд
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьОбновленияРегистра()
// Вызываем серверную функцию, которая вернет дату последнего изменения
ДатаИзБазы = ПолучитьДатуПоследнегоИзмененияНаСервере();
Если ДатаИзБазы > ПоследняяДатаПроверки Тогда
ПоследняяДатаПроверки = ДатаИзБазы;
// Только здесь выполняем "тяжелое" действие: открываем окно или обновляем список
ПоказатьОповещениеПользователя("Обновление", , "Появились новые данные!");
КонецЕсли;
КонецПроцедуры
В обсуждении на форуме упоминалось использование фоновых заданий. Разберем, насколько это эффективно. Само по себе ФоновоеЗадание работает на сервере и не может напрямую взаимодействовать с интерфейсом пользователя (например, открыть форму или вывести Предупреждение). Однако оно может служить отличным инструментом для мониторинга сложных условий.
Представим ситуацию: уведомление должно срабатывать не просто при создании записи, а при выполнении сложного условия (например, если сумма в регистре превысила лимит). В этом случае:
Этот подход позволяет разгрузить клиентские сеансы от сложных вычислений, перенося логику анализа на сервер.
Мы проанализировали три основных подхода к реализации уведомлений. Для современных конфигураций на платформе 8.3.12 (особенно в веб-клиенте) безусловным фаворитом является Система взаимодействия. Она обеспечивает минимальную задержку и практически не создает лишнего трафика. Если же вы ограничены использованием обработчика ожидания, обязательно внедряйте механизм «флагов» или дат изменения, чтобы избежать деградации производительности сервера при большом количестве активных пользователей.