Проблема длительного ожидания при выполнении интеграционных задач — одна из самых распространенных в практике разработчика 1С. Типичная ситуация: при записи документа в текущей базе программный код инициализирует COMОбъект("V83.COMConnector"), подключается к удаленному ресурсу и создает там объект. В это время пользователь веб-клиента видит вращающийся индикатор или получает назойливые вопросы от браузера о необходимости подождать. Разберем детально, почему это происходит и как перевести систему на современные рельсы, обеспечив комфортную работу пользователей.
Прежде чем переходить к коду, проанализируем ситуацию. Использование COM-соединителя — это «тяжелая» операция. При каждом вызове происходит инициализация полноценного сеанса в целевой базе, проверка лицензий, загрузка конфигурации в память и настройка прав доступа. Если база-приемник работает медленно или сервер перегружен, процесс может занимать от нескольких секунд до минуты. В веб-клиенте это критично, так как таймауты браузеров жестко ограничены.
Важный нюанс: Часто разработчики совершают ошибку, помещая код создания COM-объекта в модуль объекта в процедуру ПередЗаписью или ПриЗаписи. Это приводит к тому, что транзакция записи основного документа остается открытой до тех пор, пока не завершится работа во второй базе. Если произойдет сбой связи, заблокированными окажутся таблицы в обеих базах.
Рассмотрим самый эффективный способ «освободить» интерфейс пользователя — запуск фонового задания. Вместо того чтобы заставлять пользователя ждать ответа от другой базы, мы мгновенно завершаем запись в текущей базе, а задачу по созданию документа передаем серверному потоку.
Для реализации этого метода нам необходимо вынести код интеграции в процедуру ПослеЗаписиНаСервере (в модуле формы) или использовать механизм ФоновыеЗадания.Выполнить(). Проанализируем пример кода:
// В модуле формы документа
&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
// Подготовим параметры для передачи в фоновое задание
СтруктураПараметров = Новый Структура;
СтруктураПараметров.Вставить("СсылкаНаДокумент", ТекущийОбъект.Ссылка);
// Запускаем асинхронное выполнение
ФоновыеЗадания.Выполнить("ИнтеграцияСервер.СоздатьДокументВБухгалтерии",
Новый Массив(СтруктураПараметров));
КонецПроцедуры
В этом случае управление возвращается пользователю сразу после нажатия кнопки «Записать». Создание документа в другой базе происходит в фоне. Если пользователю критично знать результат, мы можем настроить механизм оповещения через Систему взаимодействия или через обработчик ожидания, который проверит статус выполнения задания.
Если нам нужна гарантированная доставка данных, даже если целевая база временно недоступна, рассмотрим архитектуру с использованием «буфера». Создадим регистр сведений ОчередьИнтеграции, куда при записи документа будем помещать ссылку на него и признак состояния (например, «Не обработан»).
Разберем алгоритм по шагам:
ПриЗаписи (или после нее) добавляем запись в регистр сведений.РегламентноеЗадание, которое будет запускаться раз в 1-5 минут.Посмотрим на пример кода регламентного задания:
Процедура ВыполнитьОбменСБазойПриемником() Экспорт
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ДокументСсылка ИЗ РегистрСведений.ОчередьИнтеграции ГДЕ Статус = &Статус";
Запрос.УстановитьПараметр("Статус", Перечисления.СтатусыОбмена.НеОбработан);
Результат = Запрос.Выполнить().Выбрать();
Если Результат.Количество() > 0 Тогда
// Инициализируем соединение один раз для всех документов
COMСоединение = ПодключитьсяКБазеПриемнику();
Пока Результат.Следующий() Цикл
Попытка
// Логика создания документа в приемнике
СоздатьОбъектВПриемнике(COMСоединение, Результат.ДокументСсылка);
УстановитьСтатусУспеха(Результат.ДокументСсылка);
Исключение
ЗаписатьЛогОшибки(ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Преимущества: Экономия на времени подключения к COM (оно происходит один раз для пачки документов), отсутствие влияния на скорость работы пользователя и устойчивость к сбоям сети.
Как отмечалось в обсуждении, COMConnector — это устаревающая технология. Если есть возможность изменить архитектуру, мы настоятельно рекомендуем использовать HTTP-сервисы. Вместо того чтобы поднимать тяжелую COM-сессию, текущая база отправляет легкий HTTP-запрос (POST) с данными в формате JSON.
Выясним причину, почему это быстрее:
Пример отправки данных через HTTP:
Соединение = Новый HTTPСоединение("192.168.1.10", , "User", "Password");
Запрос = Новый HTTPЗапрос("/Base/hs/v1/create_doc");
Запрос.УстановитьТелоИзСтроки(ДанныеJSON);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния <> 200 Тогда
// Обработка ошибки
КонецЕсли;
Если отказаться от COM невозможно, проанализируем ситуацию с его оптимизацией. В обсуждении предлагалось использовать Модули с повторным использованием значений. Это позволяет хранить объект COM-соединения в памяти сервера в течение определенного времени (по умолчанию 20 минут).
Рассмотрим реализацию:
ИнтеграцияПовторноеИспользование.
Функция ПолучитьCOMСоединение() Экспорт
Connector = Новый COMОбъект("V83.COMConnector");
Возврат Connector.Connect("Srvr='ServerName';Ref='BaseName';Usr='Admin';Pwd='123'");
КонецФункции
Важно: Метод имеет недостатки. COM-объект может «зависнуть» или соединение может быть разорвано со стороны сервера, а переменная в модуле все еще будет содержать ссылку на него. Потребуется дополнительная проверка на Живость соединения через Попытка...Исключение.
При работе с COM-объектами в среде 1С часто возникают специфические проблемы, которые мы должны учитывать:
dllhost.exe через «Службы компонентов» Windows (создание COM+ приложения).Connect() внутри активной транзакции записи. Это прямой путь к дедлокам (взаимным блокировкам).Подводя итог нашему анализу, выделим идеальную стратегию решения проблемы:
Шаг 1: Перенесите код создания документа из модуля объекта в модуль формы или используйте подписки на события, чтобы избежать выполнения кода внутри основной транзакции.
Шаг 2: Оберните вызов создания документа в фоновое задание. Это решит проблему «зависания» интерфейса в браузере.
Шаг 3: В долгосрочной перспективе откажитесь от COM в пользу HTTP-сервисов. Это сделает вашу систему более масштабируемой и стабильной.
Помните, что «бесшовная интеграция» не должна означать «синхронная». Пользователь не должен платить своим временем за то, что данные передаются в другие системы.