Почему параметр сеанса типа ФиксированныйМассив доступен в отладчике, но вызывает ошибку при чтении в коде?

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

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

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

Особенности жизненного цикла параметров сеанса

Прежде чем перейти к программным ошибкам, зафиксируем два фундаментальных принципа работы платформы:

  1. Параметры сеанса не сохраняются между перезапусками клиента. Сеанс пользователя на сервере уникален. При каждом новом входе в базу создается новый сеанс, и все его параметры изначально находятся в неинициализированном состоянии. Заполнить параметр в предыдущем сеансе и прочитать его в следующем невозможно.
  2. Отсутствие значения по умолчанию. В отличие от обычных переменных, неинициализированный параметр сеанса не равен значению Неопределено. Любая попытка прочитать неинициализированный параметр сеанса напрямую приводит к падению с ошибкой получения атрибута контекста.

Механизм работы процедуры УстановкаПараметровСеанса

Платформа 1С использует механизм отложенной (ленивой) инициализации. Это означает, что параметры сеанса заполняются не скопом при старте приложения, а в момент первого обращения к ним в коде или в запросах системы компоновки данных и ограничений доступа (RLS).

Когда система обнаруживает попытку чтения неинициализированного параметра, управление автоматически передается в модуль сеанса в предопределенную процедуру УстановкаПараметровСеанса(ТребуемыеПараметры). Проанализируем, почему возникает парадокс с отладчиком:

  1. Точечное обращение из кода или отладчика. Когда выполняется строка ПараметрыСеанса.ТекущиеГруппы, платформа передает в параметр процедуры ТребуемыеПараметры фиксированный массив, содержащий ровно одну строку — "ТекущиеГруппы".
  2. Вычисление всей коллекции. Когда в отладчике вычисляется весь объект ПараметрыСеанса, платформа запрашивает значения абсолютно всех параметров сеанса сразу. В этом случае в процедуру УстановкаПараметровСеанса передается ТребуемыеПараметры = Неопределено.

Если в модуле сеанса проверка условия написана с ошибкой (например, ветка инициализации проверяет только равенство значению Неопределено или проверяет имена с ошибкой в регистре), то при точечном обращении код инициализации просто пропускается. Обработчик завершает работу, платформа видит, что запрошенный параметр так и остался пустым, и генерирует исключение. Когда же вычисляется весь объект целиком, срабатывает ветка для Неопределено, параметр инициализируется, и после этого отладчик успешно читает его значение.

Причины повторного входа в модуль сеанса и зацикливания

Еще одна частая проблема при инициализации списков групп и ролей — повторный вызов процедуры модуля сеанса при попытке прочитать параметр. Выясним основные причины такого поведения:

  1. Срабатывание механизма RLS (ограничение прав на уровне записей). Если процедура заполнения параметра выполняет запрос к таблицам базы данных (например, к справочнику пользователей или регистру сведений о группах), платформа применяет действующие ограничения доступа. Если в шаблоне RLS задействован параметр сеанса, который еще не инициализирован, чтение данных прерывается, и платформа рекурсивно вызывает УстановкаПараметровСеанса снова.
  2. Попытка прочитать параметр внутри процедуры его же создания. Если вызываемая функция получения данных неявно обращается к свойствам ПараметрыСеанса до присвоения значения, система уходит на повторную инициализацию.
  3. Несоответствие типов данных. Для параметров типа ФиксированныйМассив критично, чтобы возвращаемое значение всегда соответствовало типу метаданных. Если функция получения групп возвращает Неопределено (например, когда пользователь не включен ни в одну группу), попытка присвоить это значение строго типизированному параметру приведет к исключению, прерывая процедуру инициализации.

Правильная реализация инициализации параметров сеанса

Рассмотрим эталонный алгоритм инициализации параметра сеанса в модуле сеанса, исключающий зацикливание и ошибки прав доступа:


Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
    
    // Проверяем необходимость инициализации конкретного параметра
    НужноЗаполнитьГруппы = (ТребуемыеПараметры = Неопределено) 
        Или (ТребуемыеПараметры.Найти("ТекущиеГруппы") <> Неопределено);
        
    Если НужноЗаполнитьГруппы Тогда
        
        // Включаем привилегированный режим для исключения влияния RLS
        УстановитьПривилегированныйРежим(Истина);
        
        МассивГрупп = ПолучитьМассивГруппТекущегоПользователя();
        
        // Гарантируем корректность типа данных перед созданием ФиксированногоМассива
        Если МассивГрупп = Неопределено Тогда
            МассивГрупп = Новый Массив;
        КонецЕсли;
        
        ПараметрыСеанса.ТекущиеГруппы = Новый ФиксированныйМассив(МассивГрупп);
        
    КонецЕсли;
    
КонецПроцедуры

Разберем по шагам ключевые моменты этого кода:

  1. Конструкция с методом Найти() корректно отрабатывает и при общем вызове системы (когда передан Неопределено), и при точечном запросе параметра платформой.
  2. Использование метода УстановитьПривилегированныйРежим(Истина) гарантирует, что чтение состава групп текущего пользователя выполнится в обход ограничений прав на уровне записей, предотвращая каскадный повторный вызов модуля сеанса.
  3. Проверка результата на равенство Неопределено исключает ошибку несоответствия типов при инициализации объекта ФиксированныйМассив.

Как проверить, инициализирован ли параметр сеанса

В платформе 1С не предусмотрено встроенных методов вроде Свойство() или Заполнен() для объекта ПараметрыСеанса. Попытка сравнить параметр со значением Неопределено вызовет исключение еще на этапе чтения свойства.

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


Попытка
    ТекущиеГруппыПользователя = ПараметрыСеанса.ТекущиеГруппы;
    ПараметрИнициализирован = Истина;
Исключение
    ПараметрИнициализирован = Ложь;
КонецПопытки;

Однако в соответствии со стандартами разработки 1С использование блоков Попытка ... Исключение для проверки сеансовых параметров считается антипаттерном. Архитектура конфигурации должна строиться так, чтобы процедура УстановкаПараметровСеанса гарантированно отрабатывала корректно при первом же обращении к любому параметру сеанса.

← На главную