В процессе разработки интеграций между различными информационными базами на платформе 1С (например, между 1С:ERP и 1С:Бухгалтерия) программисты часто сталкиваются с ограничением стандартного механизма планов обмена. Стандартный подход работает по принципу «все или ничего»: когда база-источник получает подтверждение о приеме сообщения с определенным номером, она очищает регистрацию изменений для всех объектов, вошедших в этот пакет. Однако на практике часто возникает ситуация, когда часть документов из пакета загрузилась успешно, а один или несколько документов — нет (например, из-за некорректных данных или отсутствия связанных справочников). В таком случае нам необходимо оставить «проблемные» объекты зарегистрированными, чтобы они ушли со следующим сеансом обмена, а для успешных — снять регистрацию.
В этой статье мы подробно разберем, почему стандартный механизм ведет себя именно так, и проанализируем несколько способов реализации «пообъектного» подтверждения регистрации изменений.
Для начала давайте разберем, как работает типовой метод ПланыОбмена.УдалитьРегистрациюИзменений(). Когда мы инициируем обмен, система фиксирует номер сообщения для всех выгружаемых объектов. После успешной загрузки в базу-приемник формируется файл-ответ, содержащий номер принятого сообщения. При загрузке этого ответа в базе-источнике вызывается код:
ПланыОбмена.УдалитьРегистрациюИзменений(УзелОбмена, НомерПринятогоСообщения);
Этот метод очищает записи в таблице регистрации изменений для указанного узла по всем объектам, чей номер сообщения меньше или равен переданному. Проблема заключается в том, что внутри этой процедуры нет фильтра по конкретным объектам — она оперирует только номерами пакетов. Если мы хотим управлять процессом более тонко, нам придется изменить саму логику взаимодействия баз.
Рассмотрим наиболее гибкий подход, который можно внедрить в уже существующий обмен через файлы (XML/JSON). Идея заключается в том, чтобы в файле-ответе передавать не просто номер сообщения, а детальный список идентификаторов (GUID), которые не удалось загрузить.
Алгоритм реализации:
Попытка...Исключение.УникальныйИдентификатор в массив ошибок.УдалитьРегистрациюИзменений() (который очистит всё), мы запускаем цикл по полученному массиву ошибок и заново регистрируем эти объекты на узле.Посмотрим на пример кода в базе-источнике при обработке файла-ответа:
// 1. Стандартная очистка по номеру сообщения
ПланыОбмена.УдалитьРегистрациюИзменений(УзелОбмена, СтруктураОтвета.НомерСообщения);
// 2. Повторная регистрация объектов с ошибками
Для Каждого ТекущийИдентификатор Из СтруктураОтвета.СписокОшибочныхGUID Цикл
// Находим ссылку на объект по GUID (нужно знать тип объекта или искать перебором)
СсылкаНаОбъект = НайтиСсылкуПоИдентификатору(ТекущийИдентификатор);
Если Не СсылкаНаОбъект.Пустая() Тогда
ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, СсылкаНаОбъект);
КонецЕсли;
КонецЦикла;
Этот способ позволяет «вернуть» объект в очередь обмена, и он будет выгружен повторно при следующем запуске регламентного задания.
Проанализируем более продвинутый вариант, который используется в некоторых типовых решениях (например, в бесшовной интеграции 1С:ERP и 1С:Документооборот). Здесь мы отказываемся от прямой работы с таблицей регистрации изменений при выгрузке.
Суть метода:
ОчередьСообщенийИнтеграции).ОчередьСообщенийИнтеграции и сразу очищает регистрацию в плане обмена.ОчередьСообщенийИнтеграции удаляется только тогда, когда из базы-приемника получено подтверждение по конкретному объекту (по его идентификатору).Такой подход гарантирует, что пока объект не будет физически записан в приемнике, запись о необходимости его передачи будет «висеть» в нашей самописной очереди в источнике. Это избавляет от проблем с номерами сообщений, но требует разработки собственной логики формирования пакетов.
Выясним, можно ли вообще уйти от асинхронного подтверждения. Если объем данных невелик, а канал связи стабилен, самым надежным решением будет использование HTTP-сервисов.
При таком подходе база-источник передает данные в приемник и в рамках того же соединения получает ответ о результате загрузки. Если приемник вернул код 200 (ОК), источник выполняет:
ПланыОбмена.УдалитьРегистрациюИзменений(УзелОбмена, СсылкаНаОбъект);
Если же приемник вернул ошибку, регистрация просто не снимается. Это исключает необходимость сложной логики с перерегистрацией или очередями сообщений. Однако помните, что для больших объемов данных (тысячи документов) этот метод может привести к длительным блокировкам и таймаутам.
Если ваша конфигурация построена на Библиотеке стандартных подсистем (БСП), стоит обратить внимание на подсистему «Обмен данными». В современных версиях БСП существует регистр сведений РезультатыОбменаДанными. Разберем, как его использовать:
ОбменДаннымиСервер.ЗарегистрироватьИзмененияДляУзла(), можно гибко управлять очередью выгрузки.При внедрении ручного управления регистрацией изменений важно учитывать следующие нюансы:
КоличествоПопытокОтправки. После 5–10 неудачных попыток объект должен попадать в «карантин» и уведомлять администратора.УдалитьРегистрациюИзменений(Узел, Объект) работает медленнее, чем массовая очистка по номеру сообщения. На больших базах это может вызвать блокировки таблицы Chng (таблица изменений). Старайтесь группировать объекты при обработке.Таким образом, хотя «из коробки» 1С предлагает только пакетный метод подтверждения, мы имеем широкий инструментарий для реализации пообъектного контроля. Выбор метода зависит от сложности вашей системы и требований к отказоустойчивости интеграции.