Как сохранить и передать переменную в общем модуле при HTTP-соединении

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

При разработке HTTP-сервисов в среде 1С:Предприятие, особенно когда речь заходит о создании Telegram-ботов или сложных интеграций, разработчики часто сталкиваются с фундаментальной особенностью платформы: HTTP-запросы по своей природе являются "stateless" (без сохранения состояния). Это означает, что переменная, объявленная в одном запросе, не будет существовать в другом. Давайте подробно разберем, как обойти это ограничение, какие механизмы предоставляет платформа 1С и как избежать проблем с производительностью.

Почему обычные переменные не работают

Проанализируем ситуацию: когда внешний сервис (например, сервер Telegram) обращается к вашему HTTP-сервису в 1С, создается отдельный поток или используется сеанс из пула. Как только выполнение метода завершается, контекст очищается. Попытка объявить переменную в разделе описания переменных общего модуля не даст желаемого результата — при следующем вызове она снова будет пустой или недоступной. Рассмотрим эффективные способы решения этой задачи.

Способ 1. Передача данных через параметры функций

Это самый правильный архитектурный подход. Если ваша логика в рамках одного HTTP-вызова уходит глубоко в общие модули, не пытайтесь найти "глобальную переменную". Мы рекомендуем передавать необходимые данные (токены, ID пользователя, текущее состояние) непосредственно в параметрах процедур и функций.

Рассмотрим пример структуры вызова:


// В обработчике HTTP-сервиса
Процедура ОбработатьЗапрос(Запрос)
    ПараметрыОбработки = Новый Структура;
    ПараметрыОбработки.Вставить("ПользовательID", "12345");
    ПараметрыОбработки.Вставить("ТекущийШаг", 2);
    
    МойОбщийМодуль.ВыполнитьЛогику(ПараметрыОбработки);
КонецПроцедуры

Способ 2. Использование параметров сеанса

Многие разработчики задаются вопросом: работают ли ПараметрыСеанса в условиях HTTP-соединения? Ответ — да, но с важной оговоркой. Для того чтобы параметры сеанса сохранялись между разными HTTP-запросами, клиент должен поддерживать механизм Cookie и возвращать идентификатор сессии v8-session-id. Если это условие выполняется, 1С будет использовать один и тот же сеанс из пула, и данные будут доступны.

Разберем, как правильно инициализировать такие параметры через МодульСеанса:


Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
    // Здесь можно инициализировать значения по умолчанию для HTTP-запросов
    Если ПараметрыСеанса.ТекущийПользовательБот.Пустая() Тогда
        ПараметрыСеанса.ТекущийПользовательБот = Справочники.ВнешниеПользователи.НайтиПоНаименованию("TelegramBot");
    КонецЕсли;
КонецПроцедуры

Способ 3. Использование Хранилища общих настроек

Если вам нужно сохранить данные, которые должны "пережить" перезапуск сеанса или передаваться между разными вызовами, можно использовать ХранилищеОбщихНастроек. Однако помните, что этот механизм работает медленнее, чем оперативная память, так как данные записываются в системные таблицы базы данных.

Посмотрим на пример реализации функций для сохранения и чтения настроек:


Функция СохранитьХранимуюНастройку(ИмяНастройки, Значение) Экспорт 
    УстановитьПривилегированныйРежим(Истина); 
    ХранилищеОбщихНастроек.Сохранить("ГруппаНастроек_Бот", ИмяНастройки, Значение, "ОписаниеНастройки"); 
КонецФункции 

Функция ВосстановитьХранимуюНастройку(ИмяНастройки) Экспорт 
    УстановитьПривилегированныйРежим(Истина); 
    Возврат ХранилищеОбщихНастроек.Загрузить("ГруппаНастроек_Бот", ИмяНастройки); 
КонецФункции

Важное замечание: в обсуждениях отмечается, что при большом количестве переменных (более 5-10) работа через этот механизм может замедляться. Выясним причину: каждое обращение к хранилищу провоцирует транзакционную активность. Если запросов много, это создаст очередь блокировок.

Способ 4. Регистры сведений как хранилище состояний

Для высоконагруженных систем, таких как Telegram-боты с тысячами пользователей, идеальным решением будет использование непериодического регистра сведений. Это позволяет хранить любое количество "переменных" в привязке к ключу (например, ID чата).

Преимущества использования регистров:

  1. Быстрый доступ: Использование МенеджерЗаписи позволяет мгновенно получать и изменять данные.
  2. Типизация: Вы можете хранить простые типы в отдельных ресурсах, что работает быстрее, чем упаковка в двоичные данные.
  3. ХранилищеЗначения: Если нужно сохранить сложный список или массив, используйте ресурс с типом ХранилищеЗначения.

Пример записи данных в регистр:


МенеджерЗаписи = РегистрыСведений.СостоянияБота.СоздатьМенеджерЗаписи();
МенеджерЗаписи.ИдентификаторПользователя = "ID_123";
МенеджерЗаписи.Прочитать();

Если Не МенеджерЗаписи.Выбран() Тогда
    МенеджерЗаписи.ИдентификаторПользователя = "ID_123";
КонецЕсли;

МенеджерЗаписи.ПоследняяПеременная = "Значение";
МенеджерЗаписи.Записать();

Способ 5. Хранение сложных типов (Списки значений, Массивы)

Часто возникает вопрос: как хранить в таких "переменных" списки значений? Прямая запись в константы или простые поля регистра невозможна. Проанализируем решение через ХранилищеЗначения. Этот объект позволяет упаковать любой сериализуемый объект 1С в двоичные данные.

Разберем алгоритм действий:

  1. Создаем нужный объект (например, СписокЗначений).
  2. Помещаем его в Новый ХранилищеЗначения(МойСписок).
  3. Записываем полученный объект в ресурс регистра или в константу с соответствующим типом.
  4. При чтении используем метод Получить().

Рекомендация по архитектуре: Stateless и Callback Data

Рассмотрим современный подход, который активно применяется в разработке ботов. Чтобы вообще не плодить переменные на стороне сервера 1С, старайтесь передавать текущее состояние диалога в самом сообщении (например, в кнопках inline keyboard в Telegram). Когда пользователь нажимает кнопку, 1С получает в объекте callback_query всё необходимое состояние. Это полностью снимает проблему "видимости переменных в общем модуле", так как данные приходят извне вместе с запросом.

Итоги

Выбор метода зависит от ваших задач:

Использование глобальных переменных в общих модулях для HTTP-сервисов является архитектурной ошибкой, которой следует избегать в пользу описанных выше механизмов.

← На главную