В процессе эксплуатации конфигурации «1С:Управление торговлей» на платформе «1С:Предприятие 8.3» часто возникает ситуация, когда массовые операции (например, проведение документа Отчет о розничных продажах при закрытии смены) выполняются одновременно десятками пользователей. В пиковые часы — перед закрытием торговых точек — это приводит к жестким конфликтам блокировок данных СУБД и ошибкам у пользователей.
Для решения проблемы блокировок эффективной стратегией является вынос тяжелой обработки в очередь на сервере через регистр сведений с последующим выполнением в фоновом или регламентном задании. Однако в этом случае возникает задача: как аккуратно и без лишней нагрузки на сервер уведомить конкретного пользователя в тонком клиенте о том, что его смена успешно закрыта или при обработке произошла ошибка?
Разберем подробнее варианты построения этого механизма и проанализируем оптимальные технические решения.
Выясним причину, почему при нажатии кнопки «Закрытие смены» одновременно десятками пользователей возникают конфликты. В типовых конфигурациях обработка закрытия смены выполняет целую последовательность действий:
Отчет о розничных продажах.Если информационная база работает в автоматическом или смешанном режиме блокировок, СУБД может заблокировать не только конкретную кассу или склад, но и целиком таблицы или индексы итогов. Если же выключено свойство Разделение итогов у активных регистров накопления, параллельная запись из 30–80 сеансов неизбежно вызывает взаимные блокировки (deadlocks).
Создание промежуточной очереди в регистре сведений с последующим последовательным проведением через регламентное задание устраняет пиковую нагрузку на СУБД. Но чтобы интерфейс тонкого клиента оставался отзывчивым, необходимо правильно настроить обратную связь с пользователем.
Рассмотрим основной способ оповещения с использованием метода глобального контекста ПодключитьОбработчикОжидания.
Главная ошибка при реализации этого подхода — оставлять обработчик ожидания постоянно включенным (например, раз в 5 минут для всех пользователей). Если в системе работают десятки точек, фоновые постоянные опросы создадут бессмысленную нагрузку на сервер приложений.
Правильная схема работы выглядит следующим образом:
ОтключитьОбработчикОжидания.Посмотрим на пример программной реализации этого алгоритма:
&НаКлиенте
Процедура КомандаЗакрытьСмену(Команда)
// Передаем данные на сервер и получаем уникальный идентификатор задачи
ИдентификаторЗадачи = ПоместитьЗадачуВОчередьНаСервере();
// Сохраняем ID задачи в параметрах формы или сеансовых переменных
ЭтаФорма.ТекущаяЗадачаИД = ИдентификаторЗадачи;
// Подключаем опрос сервера каждые 3 секунды
ПодключитьОбработчикОжидания("ПроверитьЗавершениеЗакрытияСмены", 3);
ПоказатьОповещениеПользователя("Обработка", , "Запрос на закрытие смены отправлен в очередь...");
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьЗавершениеЗакрытияСмены()
// Проверяем состояние задачи на сервере
РезультатЗадачи = ПолучитьCтатусЗадачиНаСервере(ЭтаФорма.ТекущаяЗадачаИД);
Если РезультатЗадачи.Статус = "Завершено" Тогда
// Отключаем обработчик, чтобы не загружать сервер
ОтключитьОбработчикОжидания("ПроверитьЗавершениеЗакрытияСмены");
// Информируем пользователя
ПоказатьОповещениеПользователя(
"Закрытие смены",
,
"Смена успешно закрыта! Сформирован отчет: " + Строка(РезультатЗадачи.ДокументСсылка)
);
ИначеЕсли РезультатЗадачи.Статус = "Ошибка" Тогда
ОтключитьОбработчикОжидания("ПроверитьЗавершениеЗакрытияСмены");
ПоказатьОповещениеПользователя(
"Ошибка закрытия смены",
,
РезультатЗадачи.ТекстОшибки,
СтатусОповещения.Ошибка
);
КонецЕсли;
КонецПроцедуры
Помимо подключения обработчиков ожидания вручную, существует несколько встроенных механизмов платформы и стандартных библиотек, которые позволяют решить задачу оповещения еще более эффективно.
ДлительныеОперации и ДлительныеОперацииКлиент предоставляют готовый инструментарий для запуска фоновых процессов и отслеживания их прогресса. Функция ДлительныеОперацииКлиент.ОжидатьЗавершение берет на себя управление интервалами опроса, отображение индикатора выполнения и возврат результата в клиентский сеанс.БлокировкаДанных по конкретным реквизитам (КассаККМ, Организация, Склад) проведение документов разных кассовых смен будет выполняться параллельно без взаимных пересечений и задержек.Таким образом, комбинируя очередь фоновых задач с точечным вызовом ПодключитьОбработчикОжидания или механизмами БСП, можно полностью исключить пиковые блокировки и обеспечить оперативную обратную связь для пользователей тонкого клиента.