В процессе разработки конфигураций на платформе 1С:Предприятие 8.3 одним из ключевых механизмов управления контекстом пользователя являются параметры сеанса. Они представляют собой глобальные переменные, значения которых сохраняются на протяжении всего сеанса работы пользователя с базой данных. Однако у начинающих (а иногда и у опытных) разработчиков часто возникает вопрос: как именно происходит инициализация этих параметров, откуда в предопределенной процедуре УстановкаПараметровСеанса модуля сеанса берутся имена конкретных параметров и как правильно спроектировать этот процесс без ущерба для производительности системы?
В данной статье мы подробно разберем весь жизненный цикл параметров сеанса, проанализируем внутренние механизмы платформы, рассмотрим практические примеры кода, а также изучим подводные камни, с которыми можно столкнуться при использовании БСП (Библиотеки Стандартных Подсистем), отладке и работе с фоновыми заданиями.
Давайте разберем базовый алгоритм работы платформы. В модуле сеанса существует предопределенный обработчик события УстановкаПараметровСеанса(ИменаПараметровСеанса). Параметр ИменаПараметровСеанса представляет собой массив, содержащий имена тех параметров, которые система требует инициализировать в данный момент. Нам важно понять, что вызов этого обработчика происходит в двух принципиально разных ситуациях:
ИменаПараметровСеанса при этом имеет значение Неопределено. Это сигнал для разработчика о том, что система только начинает работу.УстановкаПараметровСеанса и передает в массиве ИменаПараметровСеанса имя именно того параметра, к которому было обращение. После успешного завершения процедуры управление возвращается к исходному коду, и чтение параметра проходит без ошибок.Рассмотрим типичное заблуждение: многие разработчики полагают, что абсолютно все параметры сеанса необходимо заполнять сразу при старте системы. Это серьезная архитектурная ошибка. Если при запуске инициализировать тяжелые параметры (например, считывать сложные настройки прав доступа, персональные настройки пользователя, таблицы значений), время авторизации пользователя в системе может критически увеличиться. Особенно это критично при работе через веб-клиент или при медленном интернет-соединении.
Давайте проанализируем, как должен выглядеть качественный и производительный код в модуле сеанса. Мы применим стратегию разделения логики: при старте системы мы инициализируем только самый минимум, а все остальные параметры будем заполнять исключительно по требованию (когда к ним обращается код).
Рассмотрим пример кода в модуле сеанса:
Процедура УстановкаПараметровСеанса(ИменаПараметровСеанса)
// Определяем, запущен ли процесс инициализации по требованию (конкретные параметры)
// или это глобальный старт системы (ИменаПараметровСеанса = Неопределено)
ЗаполнятьВсе = (ИменаПараметровСеанса = Неопределено);
// Группа 1: Базовые параметры, необходимые ВСЕГДА при старте системы
Если ЗаполнятьВсе Или ИменаПараметровСеанса.Найти("ТекущийПользователь") <> Неопределено Тогда
ПараметрыСеанса.ТекущийПользователь = НайтиИлиСоздатьТекущегоПользователя();
КонецЕсли;
// Группа 2: Ленивая (отложенная) инициализация тяжелых параметров
Если ЗаполнятьВсе Или ИменаПараметровСеанса.Найти("ГраницыДоступаПользователя") <> Неопределено Тогда
// Этот параметр будет рассчитан только тогда, когда система или запрос RLS обратится к нему
ПараметрыСеанса.ГраницыДоступаПользователя = ПолучитьГраницыДоступа(ПараметрыСеанса.ТекущийПользователь);
КонецЕсли;
Если ЗаполнятьВсе Или ИменаПараметровСеанса.Найти("ТекущийСклад") <> Неопределено Тогда
// Параметр заполнится только при открытии складских документов или отчетов
ПараметрыСеанса.ТекущийСклад = ПолучитьОсновнойСкладПользователя(ПараметрыСеанса.ТекущийПользователь);
КонецЕсли;
КонецПроцедуры
В данном примере мы используем метод Найти() для анализа содержимого массива ИменаПараметровСеанса. Если платформа затребовала конкретный параметр (например, ТекущийСклад), мы инициализируем только его, экономя серверные ресурсы и время пользователя.
Выясним важную техническую деталь, вокруг которой часто возникают споры на форумах. Что происходит при попытке записи в неинициализированный параметр сеанса?
Если мы пишем конструкцию:
ПараметрыСеанса.ИмяПараметра = "НовоеЗначение";
Вызовет ли это обработчик УстановкаПараметровСеанса? Ответ: нет, не вызовет (начиная со стабильных релизов платформы 8.3). Платформа просто запишет новое значение в параметр сеанса, и он будет считаться инициализированным. Обработчик вызывается только при попытке чтения (или неявного обращения через точку) значения, которое еще не задано.
Однако будьте аккуратны с конструкциями вида:
ПараметрыСеанса.ИмяПараметра.МетодОбъекта();
В этом случае происходит неявное чтение свойства ИмяПараметра для последующего вызова метода, что гарантированно спровоцирует вызов процедуры инициализации.
Если мы ведем разработку в типовой конфигурации (например, 1С:ERP, 1С:Управление торговлей или 1С:Бухгалтерия), напрямую изменять модуль сеанса крайне не рекомендуется. Это существенно усложнит поддержку и последующее обновление конфигурации. В БСП предусмотрен готовый и безопасный механизм интеграции собственных параметров сеанса.
Давайте разберем по шагам, как добавить свой параметр сеанса в конфигурации на БСП:
МойУникальныйПараметр) и задаем ему соответствующий тип данных.ОбщегоНазначенияПереопределяемый и процедуру ПриДобавленииОбработчиковУстановкиПараметровСеанса.
Процедура ПриДобавленииОбработчиковУстановкиПараметровСеанса(Обработчики) Экспорт
// Регистрируем обработчик для нашего параметра сеанса
Обработчик = Обработчики.Добавить();
Обработчик.ИмяПараметра = "МойУникальныйПараметр";
Обработчик.Обработчик = "МойОбщийМодульСервер.УстановитьМойУникальныйПараметр";
КонецПроцедуры
Теперь, когда система или ваш код впервые обратится к ПараметрыСеанса.МойУникальныйПараметр, БСП автоматически перенаправит вызов в указанную процедуру УстановитьМойУникальныйПараметр вашего неглобального общего модуля, где вы сможете безопасно и быстро заполнить значение.
Рассмотрим ключевые технические нюансы и "подводные камни", с которыми регулярно сталкиваются разработчики при реальном внедрении систем.
Вы можете столкнуться с ситуацией, когда при пошаговой отладке в модуле сеанса код ведет себя непредсказуемо, а процедура УстановкаПараметровСеанса вызывается спонтанно без видимых причин. Почему так происходит?
Причина кроется в самом механизме работы конфигуратора. Если во время сеанса отладки у вас открыто окно Табло или вы используете инструмент Вычислить выражение (сочетание клавиш Shift + F9) и там записано выражение вида ПараметрыСеанса.НужныйПараметр, то отладчик при остановке на любой точке останова пытается вычислить текущее значение этого выражения на сервере. Сам факт этого запроса отладчика платформа расценивает как штатное обращение к параметру и неявно запускает его инициализацию. Это может запутать разработчика, создавая иллюзию того, что параметр запрашивается кодом самой конфигурации.
Это один из важнейших аспектов серверной архитектуры 1С. Параметры сеанса жестко изолированы в рамках конкретного пользовательского сеанса. Когда вы запускаете фоновое задание (например, через встроенную функцию ФоновыеЗадания.Выполнить), платформа создает на сервере новый, изолированный фоновый сеанс.
Этот фоновый сеанс:
УстановкаПараметровСеанса в контексте этого фонового сеанса.Отсюда вытекает критическая ошибка: если логика вашей процедуры УстановкаПараметровСеанса завязана на клиентские методы, интерактивные формы, обращение к операционной системе текущего пользователя или получение параметров клиента, то фоновое задание мгновенно завершится аварийной ошибкой "Попытка получения неинициализированного значения параметра сеанса". Всегда проектируйте инициализацию параметров так, чтобы она могла корректно отработать в чистом серверном контексте фонового процесса.
Иногда параметры сеанса запрашиваются абсолютно незаметно для разработчика. Это происходит при использовании ограничений доступа на уровне записей (RLS). В шаблонах ограничений часто используются конструкции вида: &ТекущийПользователь.
Если пользователь открывает стандартную форму списка документов или строит отчет, платформа генерирует SQL-запрос к базе данных, содержащий условия RLS. Если параметры сеанса, используемые в шаблоне RLS, еще не были проинициализированы, платформа приостановит построение запроса, перейдет в привилегированный режим, выполнит процедуру УстановкаПараметровСеанса для необходимых имен и только затем вернется к выполнению исходного запроса. Учитывайте этот неявный вызов при проектировании производительности ваших RLS-схем.
В платформе 1С отсутствует метод, позволяющий проверить, установлен ли параметр сеанса, без вызова его инициализации (например, нет метода типа "Инициализирован"). Любое обращение вида:
Если ПараметрыСеанса.МойПараметр = Неопределено Тогда
считается полноценным чтением и автоматически провоцирует вызов УстановкаПараметровСеанса. Если вы хотите хранить флаг состояния инициализации, разработчики часто используют вспомогательный булев параметр сеанса (например, ПараметрыИнициализированы), который заполняется в первую очередь и сигнализирует о готовности остальных подсистем.
Используя ленивую инициализацию, аккуратно разделяя контексты фоновых заданий и придерживаясь стандартов разработки БСП, вы сможете построить надежную, быструю и легкую в обновлении систему авторизации и настройки контекста ваших пользователей.