Работа с внешними источниками данных через COM-соединение (V83.COMConnector) — это классический, но достаточно капризный механизм интеграции в экосистеме 1С:Предприятие. Нередко разработчики сталкиваются с ситуацией, когда код, успешно работающий в 99% случаев, внезапно вызывает «падение» сеанса с критической ошибкой. Особенно странным выглядит поведение системы, когда алгоритм, запущенный один раз, внезапно начинает выполняться повторно с самого начала без видимых на то команд в коде.
В этой статье мы подробно разберем, почему платформа может инициировать «второй круг» выполнения кода, к чему приводит отсутствие флагов компиляции в общих модулях и как правильно диагностировать ошибки, которые не оставляют следов в Журнале регистрации.
Рассмотрим ситуацию: у нас есть внешняя обработка, которая подключается к другой базе 1С, находит объект и пытается его записать. В какой-то момент процесс «зависает», а затем выполнение кода начинается заново с клиентской части. Проанализируем, почему это происходит.
То, что часто принимается за «магический» перезапуск, на самом деле является следствием работы механизма отказоустойчивости кластера 1С. Рассмотрим этот процесс по шагам:
Записать() через COM-объект.Access Violation), из-за чего рабочий процесс rphost, обслуживающий это соединение, аварийно завершается.Как выяснилось в ходе обсуждения проблемы, наиболее частой причиной «тихого» падения COM-соединения является обращение к программному коду, который недоступен для этого типа подключения. Выясним причину подробнее.
Когда мы создаем соединение через V83.COMConnector, в базе-приемнике инициируется сеанс с типом «Внешнее соединение». Это особый режим работы, который накладывает ограничения на доступ к общим модулям. Проанализируем настройки модуля:
ПередЗаписью) вызывается процедура из общего модуля.В обычном режиме (на клиенте) мы бы получили ошибку «Метод не обнаружен». Однако внутри COM-соединения, особенно если вызов идет глубоко в серверных процедурах, это часто приводит к критическому сбою потока выполнения. Рабочий процесс rphost просто «умирает», не успев записать ничего в Журнал регистрации.
Рассмотрим пример кода, который инициирует соединение и запись объекта. Посмотрим на типичную структуру:
// Инициализация соединения
ПараметрыПодключенияИБ = "Srvr=""" + Сервер + """; Ref=""" + База + """; Usr=""" + Логин + """; Pwd=""" + Пароль + """";
V83COMCon = Новый COMОбъект("V83.COMConnector");
Соединение = V83COMCon.Connect(ПараметрыПодключенияИБ);
// Поиск и изменение объекта
ПриемникСсылка = Соединение.Справочники.Номенклатура.НайтиПоКоду("00001");
ПриемникОбъект = ПриемникСсылка.ПолучитьОбъект();
ПриемникОбъект.Наименование = "Новое наименование";
Попытка
// Именно здесь происходит падение, если в подписках на событие
// вызывается недоступный модуль
ПриемникОбъект.Записать();
Исключение
Сообщить("Ошибка при записи: " + ОписаниеОшибки());
КонецПопытки;
Важный момент: если ошибка вызвана именно падением процесса rphost, блок Попытка...Исключение может не сработать, так как само окружение, в котором должен был обработаться код исключения, перестает существовать.
Еще одна причина, по которой COM-соединение может «зависнуть» перед падением — это попытка системы вывести модальное окно или сообщение пользователю. Проанализируем ситуацию:
В коде базы-приемника может стоять проверка вроде Если ЭтоНовый() Тогда Вопрос(...) КонецЕсли;. В режиме COM-соединения интерфейса нет. Платформа 1С пытается вывести окно вопроса, но отвечать на него некому. Сеанс ожидает ответа до срабатывания тайм-аута или до тех пор, пока диспетчер кластера не принудительно завершит «зависший» поток. Чтобы избежать этого, всегда используйте проверку типа соединения:
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
// Здесь код, исключающий интерактивные действия (Вопрос, Предупреждение)
#КонецЕсли
Или используйте системную функцию ПредложениеПлатформы() и проверяйте свойство ИнформационнаяБазаПользователи.УстановитьПараметрыСеанса, но самый простой способ — проверка ПроверкаТипаЗвонка или анализ строки соединения.
Если вы столкнулись с подобным поведением, рекомендуем выполнить следующие шаги:
EXCP и ERROR. Это единственный способ увидеть, на какой именно строке кода или на каком обращении к памяти происходит Access Violation.Неопределено. Это поможет избежать конфликтов при повторных вызовах в рамках одного серверного вызова.Часто разработчики замечают: «Я записал объект вручную, и после этого код через COM заработал». Это происходит потому, что при ручной записи могли заполниться какие-то вспомогательные регистры или кэши. При последующем вызове через COM алгоритм идет по другой ветке (так как данные уже есть), и «проблемный» участок кода (тот самый модуль без флага) просто не вызывается. Однако это лишь маскировка проблемы, которая обязательно вернется на новом объекте.
Подводя итог, помните: стабильность V83.COMConnector напрямую зависит от «чистоты» серверного кода в базе-приемнике. Отсутствие интерактивных вызовов и правильная расстановка флагов компиляции — залог того, что ваши интеграции будут работать без внезапных перезапусков и падений сервера.