При организации обмена данными между базами 1С разработчики часто сталкиваются с задачей: если из отправленной порции документов приемник смог обработать только часть (например, 9 из 10), необходимо, чтобы при следующем сеансе обмен не пересылал заново весь объем данных, а отправил только тот объект, который не был принят, вместе с новыми изменениями.
Рассмотрим подробно, поддерживается ли такое поведение в типовых конфигурациях 1С, выясним причины архитектурных ограничений стандартного механизма планов обмена и проанализируем варианты доработки системы для пообъектной повторной выгрузки.
Принцип работы типовых планов обмена в 1С
В платформах 1С предприятие типовой механизм обмена данными построен на базе планов обмена и работает по строгому правилу «все или ничего». Разберем основные причины, почему штатный обмен не умеет досылать отдельные непринятые объекты из состава одного пакета:
Пакетный принцип квитирования: Платформа фиксирует факт передачи на уровне номеров сообщений (пакетов). Когда база-источник получает от приемника подтверждение (квитанцию) о получении сообщения №N, платформа автоматически снимает регистрацию изменений со всех объектов, вошедших в это сообщение. Платформенного пообъектного подтверждения в стандартном механизме не предусмотрено.
Единая транзакция на стороне приемника: По умолчанию при загрузке XML-файла база-приемник обрабатывает весь пакет в рамках одной транзакции. Если при записи или проведении хотя бы одного документа возникает ошибка, происходит откат транзакции целиком. В результате ни один объект из этого пакета не сохраняется в приемнике, а сам пакет считается неотработанным.
Поддержка ссылочной целостности: Стандартная логика типовых конфигураций нацелена на предотвращение появления неполных или противоречивых данных (например, когда документ выгружен, а связанный с ним номенклатурный справочник или контрагент не записался из-за ошибки).
Таким образом, в типовых планах обмена (включая Библиотеку Стандартных Подсистем — БСП) механизма автоматической «досылки» отдельного документа из некогда отправленного пакета нет.
Использование обработчиков событий и свойства «Игнорировать»
В типовых конфигурациях (например, УПП или конфигурациях на БСП) разработчикам доступно управление отправкой отдельных объектов на этапе формирования пакета выгрузки с помощью специальных обработчиков планов обмена, таких как ПриОтправкеДанныхГлавному или ПриОтправкеДанныхПодчиненному.
В этих событиях мы можем принудительно отменить выгрузку конкретного объекта, установив параметр ОтправкаЭлемента в значение ОтправкаЭлементаДанных.Игнорировать.
Посмотрим на пример из типовой конфигурации УПП:
Процедура ПриОтправкеДанныхГлавному(ЭлементДанных, ОтправкаЭлемента)
Если ТипЗнч(ЭлементДанных) = мТипСправочникРегОтчеты Тогда
ОтправкаЭлемента = ОтправкаЭлементаДанных.Игнорировать;
КонецЕсли;
КонецПроцедуры
Однако этот метод позволяет лишь исключить объект из текущей выгрузки на стороне источника, но не решает проблему автоматического обнаружения некорректно загруженных документов на стороне приемника.
Способы реализации пообъектного обмена и досылки
Если задача бизнес-логики требует обязательно принимать успешно обработанную часть данных и досылать только ошибочные объекты, необходимо выйти за рамки стандартной платформенной транзакционности. Рассмотрим основные технические решения.
1. Кастомное пообъектное квитирование
Разберем алгоритм построения собственной системы подтверждений:
Загрузка в приемнике: В базе-приемнике мы отключаем единую транзакцию на весь файл и оборачиваем запись каждого объекта в отдельную блок-структуру Попытка ... Исключение.
Формирование квитанции: Приемник записывает успешно обработанные объекты, а по ошибочным фиксирует их уникальные идентификаторы (GUID или ссылки) в специальной таблице ответного сообщения (файла-квитанции).
Подтверждение пакета: Номер сообщения на уровне плана обмена подтверждается, чтобы очистить стандартную регистрацию платформы для всего пакета.
Повторная регистрация на источнике: База-источник при чтении ответного файла находит список идентификаторов с ошибками и программно вызывает метод ПланыОбмена.ЗарегистрироватьИзменения() только для тех конкретных объектов, которые приемник обработать не смог. При следующем сеансе именно они будут выгружены снова.
2. Двухэтапная загрузка через буфер
Для предотвращения потерь данных и сохранения производительности применяется загрузка через промежуточный регистр сведений:
Данные из входящего XML-пакета без выполнения сложных проверок и проведения документов записываются в буферный регистр приемника «как есть».
Фоновое задание поштучно обрабатывает записи из буферного регистра. Если документ не проводится, он помечается статусом ошибки в буфере, не влияя на обработку остальных записей.
3. Переход на HTTP-сервисы или очереди сообщений
Если обмены с досылкой являются критически важной частью системы, рекомендуем рассмотреть альтернативные архитектурные подходы вместо файловых планов обмена:
HTTP/REST-сервисы: Источник передает объекты по одному HTTP-запросом. При успехе приемник возвращает код 200 OK, и источник снимает объект с выгрузки. При ошибке (код 4xx/5xx) объект остается зарегистрированным для повторной отправки.
Шина данных или очереди сообщений (RabbitMQ): Каждый объект помещается в отдельное независимое сообщение. Если приемник сталкивается с ошибкой при обработке конкретного сообщения, оно отправляется в очередь повторной обработки (Dead Letter Queue), не мешая движению остальных данных.
Риски и ограничения пообъектного обмена
При внедрении механизма пообъектной досылки следует учитывать следующие риски:
Нарушение ссылочной целостности: Документ может успешно записаться в приемнике, но связанный с ним справочник (например, новый контрагент или договор) упадет с ошибкой. В итоге в базе образуются незаполненные реквизиты или «битые» ссылки.
Зацикливание повторных выгрузок: Если ошибка обусловлена некорректным заполнением реквизитов (а не временным сбоем сети), объект будет бесконечно регистрироваться и пересылаться при каждом обмене. Для предотвращения этого в кастомном механизме необходимо вести счетчик попыток отправки и при достижении лимита уведомлять администратора.