Где и когда 1С заполняет параметры сеанса: модуль сеанса и ленивая установка

· 9 мин

Содержание

Параметр сеанса 1С инициализируют в модуле сеанса, в процедуре-обработчике УстановкаПараметровСеанса(ТребуемыеПараметры). Значение присваивают через свойство глобального контекста: ПараметрыСеанса.ИмяПараметра = Значение. Платформа вызывает обработчик сама: один раз при старте сеанса и потом каждый раз, когда код обращается к параметру, который ещё не установлен.

Типичная ситуация: разработчик добавил параметр «ТекущаяОрганизация», прописал его в условии ограничения доступа, а пользователи при входе получают ошибку «параметр сеанса не установлен». Причина почти всегда одна: параметр создан в дереве метаданных, но в модуле сеанса ему ничего не присвоили. Ниже разобран весь путь инициализации параметра сеанса: от создания объекта до сброса значения и работы с клиента.

Что такое параметр сеанса и где он доступен

Параметр сеанса — объект метаданных из ветки Общие → Параметры сеанса. Это именованное значение, которое живёт ровно столько, сколько живёт сеанс пользователя. У каждого сеанса свой экземпляр: два бухгалтера в одной базе видят разные значения одного параметра.

Чем параметр отличается от других способов хранить данные:

  • 🔹 От глобальной переменной модуля приложения — параметр доступен на сервере и в условиях RLS, переменная живёт только на клиенте.
  • 🔹 От константы — константа общая для всей базы и пишется в таблицу, параметр у каждого сеанса свой и в базе не хранится.
  • 🔹 От модуля с повторным использованием — кеш функции нельзя прочитать из ограничения доступа, параметр сеанса можно.
  • 🔹 От хранилища настроек — настройки сохраняются между сеансами, параметр сеанса исчезает при выходе.

Где свойство ПараметрыСеанса доступно напрямую:

КонтекстДоступ к ПараметрыСеанса
Сервер (общие модули «Сервер», модули объектов, менеджеров, серверные процедуры форм)Да
Внешнее соединениеДа
Толстый клиент, обычное приложениеДа
Тонкий и веб-клиент, клиентские процедуры управляемых формНет, только через вызов сервера
Тексты ограничений доступа на уровне записей (RLS)Да, через &ИмяПараметра

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

Синтаксис: как создать и инициализировать параметр сеанса

Шаг 1. Создать объект в конфигураторе

  1. Откройте конфигуратор и дерево конфигурации.
  2. Разверните Общие → Параметры сеанса, нажмите «Добавить».
  3. Задайте имя, например ТекущийПользователь, и тип — СправочникСсылка.Пользователи.
  4. Откройте роли, которые должны читать параметр, и дайте право «Получение». Право «Установка» давайте только если код вне модуля сеанса будет менять значение без привилегированного режима.

Шаг 2. Открыть модуль сеанса

Модуль сеанса открывается из контекстного меню корня конфигурации: «Открыть модуль сеанса». В нём допустим один предопределённый обработчик — УстановкаПараметровСеанса. Модуль выполняется на сервере и в привилегированном режиме, поэтому права ролей на «Установку» здесь не проверяются.

Шаг 3. Написать обработчик

Минимальный рабочий пример для параметра со ссылкой на пользователя:

Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)

    Если ТребуемыеПараметры = Неопределено Тогда
        // Старт сеанса: устанавливаем только то, что нужно всем и дёшево
        УстановитьТекущегоПользователя();
        Возврат;
    КонецЕсли;

    // Ленивый вызов: платформа передала массив имён неустановленных параметров
    Для Каждого ИмяПараметра Из ТребуемыеПараметры Цикл
        Если ИмяПараметра = "ТекущийПользователь" Тогда
            УстановитьТекущегоПользователя();
        ИначеЕсли ИмяПараметра = "ОсновнаяОрганизация" Тогда
            УстановитьОсновнуюОрганизацию();
        КонецЕсли;
    КонецЦикла;

КонецПроцедуры

Процедура УстановитьТекущегоПользователя()

    ПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
    Ссылка = Справочники.Пользователи.НайтиПоРеквизиту(
        "ИдентификаторПользователяИБ", ПользовательИБ.УникальныйИдентификатор);
    ПараметрыСеанса.ТекущийПользователь = Ссылка;

КонецПроцедуры

Здесь предполагается, что у справочника Пользователи есть реквизит ИдентификаторПользователяИБ типа УникальныйИдентификатор. Если пользователь не найден, НайтиПоРеквизиту вернёт пустую ссылку — параметр всё равно будет установлен, и ошибки при чтении не будет.

Шаг 4. Проверить

Поставьте точку останова в обработчике и запустите отладку. Первый заход будет с ТребуемыеПараметры = Неопределено. Второй — при первом обращении к ОсновнаяОрганизация, уже с массивом из одного имени.

Ленивая инициализация: что приходит в ТребуемыеПараметры

Параметр ТребуемыеПараметры бывает в двух состояниях, и от этого зависит вся схема инициализации.

ЗначениеКогдаЧто делать
НеопределеноОдин раз при запуске сеансаУстановить параметры, без которых сеанс не работает
Массив строкПри чтении параметра, у которого ещё нет значенияУстановить только перечисленные

Ленивая установка — главный приём для скорости входа. Если параметр нужен только в одном отчёте, не стоит вычислять его каждому пользователю при запуске. Достаточно обработать его имя в ветке с массивом: первый, кто откроет отчёт, запустит инициализацию в своём сеансе.

Если внутри обработчика читается другой ещё не установленный параметр, платформа снова вызовет УстановкаПараметровСеанса с его именем. Так можно строить цепочки: «ОсновнаяОрганизация» вычисляется из «ТекущийПользователь». Но параметр нельзя читать до того, как он сам себе присвоен, — иначе обработчик зациклится.

Когда после ленивого вызова параметр так и остался без значения, при чтении возникает исключение. Поэтому в ветке с массивом присваивайте значение всегда, даже если вычислить его не удалось: пустую ссылку, Ложь, пустую строку.

Типы значений и ограничения хранения

Тип параметра задаётся в его свойствах и может быть составным. Допустимы значения, которые можно передать между сервером и клиентом и которые не изменяются после присвоения.

✅ Можно хранить:

  • примитивы: Строка, Число, Дата, Булево, УникальныйИдентификатор;
  • ссылки на справочники, документы, перечисления, планы видов характеристик;
  • ХранилищеЗначения;
  • фиксированные коллекции: ФиксированныйМассив, ФиксированнаяСтруктура, ФиксированноеСоответствие.

❌ Нельзя хранить: изменяемые Массив, Структура, Соответствие, а также ТаблицаЗначений, объекты (СправочникОбъект, ДокументОбъект) и Запрос.

Список организаций для RLS обычно кладут так:

Запрос = Новый Запрос(
    "ВЫБРАТЬ
    |    Доступ.Организация
    |ИЗ
    |    РегистрСведений.ДоступКОрганизациям КАК Доступ
    |ГДЕ
    |    Доступ.Пользователь = &Пользователь");
Запрос.УстановитьПараметр("Пользователь", ПараметрыСеанса.ТекущийПользователь);
Список = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Организация");
ПараметрыСеанса.ДоступныеОрганизации = Новый ФиксированныйМассив(Список);

Регистр ДоступКОрганизациям тут условный — подставьте свой источник. Тип параметра ДоступныеОрганизации в конфигураторе должен разрешать фиксированный массив.

Чтобы поменять фиксированную коллекцию, её не правят, а собирают заново: Новый Массив(ПараметрыСеанса.ДоступныеОрганизации), добавить элемент, затем снова присвоить Новый ФиксированныйМассив(...).

Жёсткого лимита на размер значения в документации нет, но не храните в параметре сеанса тяжёлые данные: значение живёт в данных сеанса на сервере и сопровождает каждый серверный вызов. Сотни ссылок — нормально. Мегабайты в ХранилищеЗначения — уже повод переделать схему.

Жизненный цикл параметра сеанса и сброс значения

Значение параметра проходит четыре стадии:

  1. Не установлен — сеанс только начался, либо значение сброшено.
  2. Установлен — после присвоения в модуле сеанса или в коде с правом «Установка».
  3. Изменён — код присвоил новое значение, старое заменено целиком.
  4. Уничтожен — сеанс завершился: пользователь вышел, сеанс удалён из консоли кластера или закончилось фоновое задание.

Принудительно вернуть параметр в состояние «не установлен» можно методом Сбросить. Ему передают массив имён:

Имена = Новый Массив;
Имена.Добавить("ДоступныеОрганизации");
ПараметрыСеанса.Сбросить(Имена);
// Следующее чтение снова вызовет УстановкаПараметровСеанса

Это удобно, когда администратор поменял права доступа и хочет, чтобы пользователь увидел изменения без перезахода. Сброс делают в коде того же сеанса — изменить значения в чужом сеансе нельзя.

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

Параметры сеанса в клиент-серверном взаимодействии

Чтение с клиента

В тонком и веб-клиенте ПараметрыСеанса недоступны. Значение получают через серверную функцию в общем модуле с флажками «Сервер» и «Вызов сервера»:

// Общий модуль РаботаСПараметрамиСервер (Сервер, Вызов сервера)
Функция ОсновнаяОрганизация() Экспорт
    Возврат ПараметрыСеанса.ОсновнаяОрганизация;
КонецФункции

Если клиент читает параметр часто, оберните вызов в общий модуль с повторным использованием возвращаемых значений «На время сеанса». Тогда сервер дёрнется один раз, а остальные обращения отработают из клиентского кеша. Минус: после Сбросить или смены значения клиентский кеш останется старым до перезапуска.

Установка с клиента

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

Фоновые и регламентные задания

Фоновое задание выполняется в отдельном сеансе. Значения параметров сеанса, которые были у пользователя, в него автоматически не переносятся: в новом сеансе отработает тот же модуль сеанса со своей логикой. Если заданию нужен, например, конкретный пользователь, передайте его ссылку в параметрах метода ФоновыеЗадания.Выполнить и внутри задания используйте её.

Регламентное задание запускается от имени пользователя, указанного в его свойствах. Модуль сеанса для такого сеанса вычислит параметры именно для этого пользователя. Если пользователь не указан, обработчик должен корректно отработать и без него — иначе задание будет падать при первом же обращении к параметру.

Инициализация параметров сеанса в типовых конфигурациях

В БП 3.0, ЗУП 3.1, УТ 11 и других конфигурациях на БСП модуль сеанса почти пустой: он передаёт управление подсистеме «Базовая функциональность». Свой код в модуль сеанса типовой конфигурации вписывать не нужно — это снимет её с поддержки и усложнит обновления.

Правильный путь — расширение конфигурации :

  1. Создайте расширение и добавьте в него собственный параметр сеанса с префиксом расширения в имени.
  2. Заимствуйте общий модуль ОбщегоНазначенияПереопределяемый.
  3. В процедуре ПриДобавленииОбработчиковУстановкиПараметровСеанса(Обработчики) добавьте строку соответствия: имя параметра → "ИмяМодуля.ИмяПроцедуры".
  4. В своём серверном общем модуле напишите процедуру установки и присвойте в ней значение.

Обработчик БСП получает имя параметра и массив уже установленных параметров, куда нужно добавить имя после присвоения. Точная сигнатура описана в комментарии к ПриДобавленииОбработчиковУстановкиПараметровСеанса вашей версии БСП — сверяйтесь с ним, а не с примерами из интернета под старые редакции.

Ошибка в модуле сеанса или обработчике установки ломает вход для всех пользователей. Проверяйте расширение на копии базы и ставьте его в рабочую базу в нерабочее время.

Производительность и типичные ошибки при инициализации

Модуль сеанса выполняется при каждом входе, поэтому всё, что в нём лежит в ветке Неопределено, добавляется ко времени запуска каждого пользователя. Правила, которые держат вход быстрым:

  • ⚡ при старте устанавливайте только то, без чего не откроется ни одна форма;
  • ⚡ остальное переносите в ленивую ветку с массивом имён;
  • ⚡ не пишите в параметр сеанса в цикле — копите значение в переменной и присваивайте один раз;
  • ⚡ не используйте параметр сеанса как счётчик или журнал: каждая запись меняет данные сеанса на сервере;
  • ⚡ в RLS держите параметры компактными: ссылка или небольшой фиксированный массив.

Распространённые сбои и их причины:

Диагностика: выберите симптом

Частые вопросы

Можно ли установить параметр сеанса в модуле управляемого приложения?
Нет. Модуль управляемого приложения выполняется на клиенте, где ПараметрыСеанса недоступны. Инициализацию делают в модуле сеанса или в серверной процедуре.
Сколько раз за сеанс вызывается УстановкаПараметровСеанса?
Один раз при старте с Неопределено и затем по одному разу на каждое обращение к неустановленному параметру. После присвоения повторного вызова для этого параметра не будет, пока его не сбросят.
Можно ли использовать параметр сеанса прямо в тексте обычного запроса?
В обычном запросе значение передают через УстановитьПараметр. Обращение вида &ИмяПараметраСеанса без передачи работает в текстах ограничений доступа на уровне записей.
Видит ли администратор значения параметров сеанса других пользователей?
Нет. Из кода доступен только свой сеанс. Чтобы понять, какое значение получил пользователь, записывайте его в журнал регистрации в момент установки.
Нужно ли давать право «Получение» полноправному пользователю?
Роль с административными правами обычно уже содержит все права. Для остальных ролей право «Получение» нужно явно, если код читает параметр без привилегированного режима.