Рассмотрим распространенную проблему, возникающую при настройке двустороннего обмена между базами 1С с использованием обработки УниверсальныйОбменДаннымиXML и планов обмена. Часто обмен настраивают через прямое COM-соединение, устанавливая флажок Обработка.НепосредственноеЧтениеВИБПриемнике = Истина. Проблема заключается в следующем: если за день регистрируется множество документов, и при выгрузке пакета один из них вызывает ошибку в базе-приемнике (например, при проведении или записи), весь процесс обмена экстренно прекращается.
При этом документы, которые успели успешно загрузиться до возникновения ошибки, не снимаются с регистрации. Когда регламентное задание запускает обмен снова, эти же документы выгружаются повторно, расходуя ресурсы и время. Выясним причину такого поведения и разберем по шагам несколько эффективных способов решения этой задачи.
Проанализируем ситуацию детальнее. Разработчики часто пытаются обернуть вызов метода выгрузки в конструкцию Попытка ... Исключение и просто не устанавливать флаг отказа в блоке исключения, надеясь, что обмен продолжится:
Попытка
Обработка.ВыполнитьВыгрузку();
Исключение
// Отказ = ИСТИНА; // Закомментировали, чтобы продолжить
Сообщение = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
ЗаписьЖурналаРегистрации("Обмен данными", УровеньЖурналаРегистрации.Ошибка, , , Сообщение);
КонецПопытки;
Однако это не работает. При использовании режима прямого чтения в приемнике через COM весь процесс выгрузки и загрузки идет в рамках единого вызова метода ВыполнитьВыгрузку(). Если на стороне базы-приемника возникает критическая ошибка (например, сбой проведения документа), COM-сервер генерирует фатальное исключение. Это исключение мгновенно «выбрасывает» процесс из цикла обработки внутри COM-объекта и возвращает ошибку в базу-источник.
Выполнение метода прерывается, и код просто не доходит до команды очистки регистрации изменений успешных объектов. Также из-за специфики COM-соединения база-источник получает лишь общую ошибку платформы, а детальное описание того, что именно не провелось в приемнике, теряется при обрыве.
Если вы хотите сохранить архитектуру на COM-соединении, ошибку необходимо перехватывать на стороне самой базы-приемника, до того, как она обрушит соединение. Сделать это можно в правилах «Конвертации данных 2».
ПослеЗагрузки или ПриЗаписи, оберните код проведения или записи в блок Попытка ... Исключение ... КонецПопытки.Отказ = Истина;.Таким образом, проблемный документ просто пропускается, исключения для COM-соединения не возникает, обработка благополучно переходит к следующему объекту пакета, а в конце успешно снимает с регистрации весь пакет.
Рассмотрим более современный и отказоустойчивый подход, к которому пришел автор темы. COM-соединения часто работают нестабильно при больших объемах данных и чувствительны к разнице версий платформ. Веб-сервисы (HTTP-запросы) работают по принципу без сохранения состояния (stateless), они намного легче переносят обрывы связи и изолируют ошибки.
Разберем логику реализации пообъектного обмена:
УниверсальныйОбменДаннымиXML.УниверсальныйОбменДаннымиXML. Если возникает ошибка, она обрабатывается и логируется локально в приемнике, а веб-сервис возвращает ответ источнику о неудаче.Посмотрим на общую схему цикла в источнике (псевдокод):
// Получаем выборку изменений
Выборка = ПланыОбмена.ВыбратьИзменения(УзелОбмена, НомерСообщения);
Пока Выборка.Следующий() Цикл
ОбъектДанных = Выборка.Получить();
// Формируем XML для одного объекта
XMLСтрока = СформироватьXMLДляОбъекта(ОбъектДанных, ПравилаОбмена);
// Отправляем через веб-сервис
Результат = ПроксиВебСервиса.ЗагрузитьОбъект(XMLСтрока);
Если Результат = "Успех" Тогда
// Снимаем регистрацию только для успешного объекта
ПланыОбмена.УдалитьРегистрациюИзменений(УзелОбмена, ОбъектДанных);
Иначе
ЗаписьЖурналаРегистрации("Обмен данными", УровеньЖурналаРегистрации.Ошибка, , ОбъектДанных, "Ошибка загрузки: " + Результат);
КонецЕсли;
КонецЦикла;
Также перед внедрением любых сложных доработок убедитесь, что в модулях объектов баз-приемников корректно обрабатывается флаг загрузки. Часто ошибки проведения при обмене возникают из-за проверок заполнения, которые должны выполняться только при интерактивной работе пользователя.
Проанализируем процедуры ПередЗаписью и ПриЗаписи. В них обязательно должна присутствовать проверка:
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Переход от громоздкого COM-соединения к пообъектной выгрузке через веб-сервисы или HTTP-сервисы является лучшей практикой при построении надежных обменов между информационными базами 1С. Это гарантирует, что ошибка в одном документе никогда не заблокирует передачу остальных критически важных данных предприятия.