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