Как обновить кэши и повторно используемые значения во всех сеансах пользователей?

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

При разработке собственных систем прав доступа, механизмов настроек или кэширования данных в 1С:Предприятие, программисты часто сталкиваются с проблемой: метод ОбновитьПовторноИспользуемыеЗначения() работает только в рамках того сеанса, в котором он был вызван. Если администратор изменил настройки прав в одном окне, у всех остальных пользователей продолжают действовать старые данные, «застрявшие» в кэше модулей повторного использования. Рассмотрим подробнее, какими способами можно решить эту задачу, проанализируем архитектурные подходы и выберем наиболее эффективные инструменты в зависимости от версии вашей платформы. Для решения проблем с застреванием прав при изменении профилей БСП пригодится обработка для точечного пересчета прав доступа.

Понимание работы модулей повторного использования

Прежде чем приступать к принудительному сбросу, давайте разберем, как платформа управляет этим кэшем. Значения в модулях с установленным свойством Повторное использование возвращаемых значений хранятся либо «На время вызова» (в рамках одной серверной транзакции), либо «На время сеанса». Проанализируем важные нюансы:

  1. Время жизни (TTL): По умолчанию платформа хранит значения в кэше сеанса около 20 минут. Если к функции не было обращений в этот период, кэш очищается автоматически.
  2. Объем памяти: Кэш не бесконечен. При заполнении выделенного объема старые значения вытесняются новыми по принципу LRU (Least Recently Used).
  3. Изоляция: Каждый сеанс (даже под одним и тем же пользователем) имеет свой изолированный кэш.

Если ваша задача требует моментального применения настроек (например, закрытие доступа к кассе), ждать 20 минут недопустимо. Выясним, как «пробить» эту изоляцию.

Способ 1: Механизм оповещения через регистр сведений (Классический подход)

Это наиболее универсальный метод, который будет работать на любой версии платформы 8.3. Суть заключается в использовании «флага» в базе данных, который считывается всеми активными клиентами. Разберем реализацию по шагам.

Шаг 1. Создание регистра. Создадим непериодический регистр сведений ОчередьОбновленияКэша. В качестве измерений добавим Пользователь (тип СправочникСсылка.Пользователи) и ИмяКомпьютера, либо просто используем один ресурс ДатаЗапроса (тип Дата).

Шаг 2. Установка обработчика ожидания. В модуле управляемого приложения пропишем код, который будет периодически проверять необходимость обновления. Рассмотрим пример кода:


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

Процедура ПроверитьНеобходимостьОбновленияКэша() Экспорт
    // Проверяем наличие записи в регистре для текущего пользователя
    Если НужноОбновитьКэшИзБазы() Тогда
        ОбновитьПовторноИспользуемыеЗначения();
        // Удаляем флаг, чтобы не обновляться по кругу
        СброситьФлагОбновленияВРегистре();
    КонецЕсли;
КонецПроцедуры

Важный нюанс: Этот способ создает небольшую, но регулярную нагрузку на базу данных. Проанализируем ситуацию: если у вас 500 пользователей и проверка идет раз в 10 секунд, это может стать заметным. Рекомендуем устанавливать интервал проверки не менее 60–120 секунд или использовать более продвинутые методы оповещения.

Способ 2: Уведомления клиента в платформе 8.3.26+

В новых версиях платформы (начиная с 8.3.26) появился мощный штатный механизм УведомленияКлиента. Он позволяет серверу отправить сигнал конкретному клиентскому сеансу без постоянных запросов со стороны клиента. Это идеальное решение для нашей задачи.

Проанализируем алгоритм работы:

  1. На клиенте при старте системы регистрируется обработчик через УведомленияКлиента.УстановитьОбработчикУведомлений().
  2. Когда администратор меняет права, на сервере вызывается УведомленияКлиента.ОтправитьУведомление().
  3. В клиентском сеансе мгновенно срабатывает процедура, в которой мы вызываем ОбновитьПовторноИспользуемыеЗначения().

Рассмотрим пример серверного кода для отправки сигнала всем сеансам конкретного пользователя:


Уведомление = Новый УведомлениеКлиента;
Уведомление.Имя = "СбросКэшаПрав";
Уведомление.Тело = "Необходимо обновить повторно используемые значения";

// Отправляем уведомление всем сеансам пользователя
УведомленияКлиента.ОтправитьУведомление(ПользовательСсылка, Уведомление);

Это решение является наиболее «чистым» с точки зрения архитектуры, так как не расходует ресурсы на бесполезные цикличные проверки.

Способ 3: Использование Системы взаимодействия (1С:Диалог)

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

  1. Создается скрытое обсуждение, на которое программно подписываются все пользователи при входе.
  2. При необходимости сброса кэша сервер отправляет сообщение в это обсуждение.
  3. В клиентском приложении срабатывает обработчик ПриПолученииСообщения.
  4. Внутри обработчика выполняется команда обновления кэша.

Этот метод работает почти мгновенно и доступен на более старых версиях 8.3 (начиная с 8.3.11).

Способ 4: Архитектурный трюк с параметром версии

Рассмотрим ситуацию, когда мы не хотим принудительно вызывать ОбновитьПовторноИспользуемыеЗначения(), так как это сбрасывает вообще все кэшированные функции, что может кратковременно снизить производительность всей системы. Можно применить «хитрость» с параметризацией.

Добавим в каждую функцию модуля повторного использования дополнительный параметр, например АктуальнаяВерсияНастроек. Значение этого параметра будем хранить в функциональной опции или константе. Посмотрим на пример:


// Функция в модуле с повторным использованием (На время сеанса)
Функция ПолучитьПраваДоступа(ИмяПользователя, ВерсияНастроек) Экспорт
    // Код получения прав...
    Возврат СтруктураПрав;
КонецФункции

Как только администратор меняет настройки, он увеличивает значение константы ВерсияНастроек в базе данных. При следующем вызове функции из кода приложения, параметр ВерсияНастроек будет уже другим. Платформа воспримет это как вызов функции с новыми входными данными и выполнит ее заново, проигнорировав старый кэш. Старые записи в кэше просто «умрут» по истечении времени. Это самый мягкий и эффективный способ для высоконагруженных систем.

Метод «Гильотины»: Завершение сеансов

Как справедливо заметили участники обсуждения, самый надежный способ очистить абсолютно все виды кэша (включая кэш метаданных и представлений ссылок) — это перезапуск сеанса. В типовых конфигурациях на базе БСП (Библиотека стандартных подсистем) есть штатная обработка «Блокировка работы пользователей».

Если изменения в системе прав носят глобальный характер (например, полное перестроение топологии доступа), рекомендуется установить блокировку соединений, завершить все активные сеансы и попросить пользователей зайти заново. Для автоматизации этого процесса на уровне системного администрирования можно использовать скрипты PowerShell для очистки папок в AppData, но это крайняя мера, применимая обычно при обновлении конфигурации или исправлении критических ошибок кэширования.

Подведем итоги

Выбор метода зависит от ваших технических условий:

Помните, что избыточное использование ОбновитьПовторноИспользуемыеЗначения() может привести к «холостому» пробегу сервера, так как ему придется заново вычислять значения, которые могли и не меняться. Используйте этот инструмент осознанно.

← На главную