При разработке собственных систем прав доступа, механизмов настроек или кэширования данных в 1С:Предприятие, программисты часто сталкиваются с проблемой: метод ОбновитьПовторноИспользуемыеЗначения() работает только в рамках того сеанса, в котором он был вызван. Если администратор изменил настройки прав в одном окне, у всех остальных пользователей продолжают действовать старые данные, «застрявшие» в кэше модулей повторного использования. Рассмотрим подробнее, какими способами можно решить эту задачу, проанализируем архитектурные подходы и выберем наиболее эффективные инструменты в зависимости от версии вашей платформы. Для решения проблем с застреванием прав при изменении профилей БСП пригодится обработка для точечного пересчета прав доступа.
Прежде чем приступать к принудительному сбросу, давайте разберем, как платформа управляет этим кэшем. Значения в модулях с установленным свойством Повторное использование возвращаемых значений хранятся либо «На время вызова» (в рамках одной серверной транзакции), либо «На время сеанса». Проанализируем важные нюансы:
Если ваша задача требует моментального применения настроек (например, закрытие доступа к кассе), ждать 20 минут недопустимо. Выясним, как «пробить» эту изоляцию.
Это наиболее универсальный метод, который будет работать на любой версии платформы 8.3. Суть заключается в использовании «флага» в базе данных, который считывается всеми активными клиентами. Разберем реализацию по шагам.
Шаг 1. Создание регистра. Создадим непериодический регистр сведений ОчередьОбновленияКэша. В качестве измерений добавим Пользователь (тип СправочникСсылка.Пользователи) и ИмяКомпьютера, либо просто используем один ресурс ДатаЗапроса (тип Дата).
Шаг 2. Установка обработчика ожидания. В модуле управляемого приложения пропишем код, который будет периодически проверять необходимость обновления. Рассмотрим пример кода:
Процедура ПриНачалеРаботыСистемы()
// Запускаем проверку раз в минуту (60 секунд)
ПодключитьОбработчикОжидания("ПроверитьНеобходимостьОбновленияКэша", 60);
КонецПроцедуры
Процедура ПроверитьНеобходимостьОбновленияКэша() Экспорт
// Проверяем наличие записи в регистре для текущего пользователя
Если НужноОбновитьКэшИзБазы() Тогда
ОбновитьПовторноИспользуемыеЗначения();
// Удаляем флаг, чтобы не обновляться по кругу
СброситьФлагОбновленияВРегистре();
КонецЕсли;
КонецПроцедуры
Важный нюанс: Этот способ создает небольшую, но регулярную нагрузку на базу данных. Проанализируем ситуацию: если у вас 500 пользователей и проверка идет раз в 10 секунд, это может стать заметным. Рекомендуем устанавливать интервал проверки не менее 60–120 секунд или использовать более продвинутые методы оповещения.
В новых версиях платформы (начиная с 8.3.26) появился мощный штатный механизм УведомленияКлиента. Он позволяет серверу отправить сигнал конкретному клиентскому сеансу без постоянных запросов со стороны клиента. Это идеальное решение для нашей задачи.
Проанализируем алгоритм работы:
УведомленияКлиента.УстановитьОбработчикУведомлений().УведомленияКлиента.ОтправитьУведомление().ОбновитьПовторноИспользуемыеЗначения().Рассмотрим пример серверного кода для отправки сигнала всем сеансам конкретного пользователя:
Уведомление = Новый УведомлениеКлиента;
Уведомление.Имя = "СбросКэшаПрав";
Уведомление.Тело = "Необходимо обновить повторно используемые значения";
// Отправляем уведомление всем сеансам пользователя
УведомленияКлиента.ОтправитьУведомление(ПользовательСсылка, Уведомление);
Это решение является наиболее «чистым» с точки зрения архитектуры, так как не расходует ресурсы на бесполезные цикличные проверки.
Если ваша платформа старше 8.3.26, но вы используете Систему взаимодействия, можно реализовать аналогичную логику через скрытые сообщения. Посмотрим на этот процесс:
ПриПолученииСообщения.Этот метод работает почти мгновенно и доступен на более старых версиях 8.3 (начиная с 8.3.11).
Рассмотрим ситуацию, когда мы не хотим принудительно вызывать ОбновитьПовторноИспользуемыеЗначения(), так как это сбрасывает вообще все кэшированные функции, что может кратковременно снизить производительность всей системы. Можно применить «хитрость» с параметризацией.
Добавим в каждую функцию модуля повторного использования дополнительный параметр, например АктуальнаяВерсияНастроек. Значение этого параметра будем хранить в функциональной опции или константе. Посмотрим на пример:
// Функция в модуле с повторным использованием (На время сеанса)
Функция ПолучитьПраваДоступа(ИмяПользователя, ВерсияНастроек) Экспорт
// Код получения прав...
Возврат СтруктураПрав;
КонецФункции
Как только администратор меняет настройки, он увеличивает значение константы ВерсияНастроек в базе данных. При следующем вызове функции из кода приложения, параметр ВерсияНастроек будет уже другим. Платформа воспримет это как вызов функции с новыми входными данными и выполнит ее заново, проигнорировав старый кэш. Старые записи в кэше просто «умрут» по истечении времени. Это самый мягкий и эффективный способ для высоконагруженных систем.
Как справедливо заметили участники обсуждения, самый надежный способ очистить абсолютно все виды кэша (включая кэш метаданных и представлений ссылок) — это перезапуск сеанса. В типовых конфигурациях на базе БСП (Библиотека стандартных подсистем) есть штатная обработка «Блокировка работы пользователей».
Если изменения в системе прав носят глобальный характер (например, полное перестроение топологии доступа), рекомендуется установить блокировку соединений, завершить все активные сеансы и попросить пользователей зайти заново. Для автоматизации этого процесса на уровне системного администрирования можно использовать скрипты PowerShell для очистки папок в AppData, но это крайняя мера, применимая обычно при обновлении конфигурации или исправлении критических ошибок кэширования.
Выбор метода зависит от ваших технических условий:
УведомленияКлиента. Это быстро и эффективно.Помните, что избыточное использование ОбновитьПовторноИспользуемыеЗначения() может привести к «холостому» пробегу сервера, так как ему придется заново вычислять значения, которые могли и не меняться. Используйте этот инструмент осознанно.