Как устранить циклическую регистрацию объектов при двухстороннем обмене между УПП 1.3 и БП 3.0

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При настройке двухстороннего обмена данными между конфигурациями Управление производственным предприятием (УПП) ред. 1.3 и Бухгалтерия предприятия (БП) КОРП ред. 3.0 разработчики часто сталкиваются с проблемой «зацикливания». Суть проблемы заключается в том, что объекты, успешно загруженные в приемник, тут же регистрируются в плане обмена для выгрузки обратно в источник. Это происходит даже в том случае, если в коде или правилах установлен стандартный признак ОбменДанными.Загрузка = Истина.

В данной статье мы подробно разберем, почему штатные механизмы платформы и БСП (Библиотеки стандартных подсистем) могут игнорировать флаг загрузки, и рассмотрим практические способы решения этой задачи с примерами кода.

Анализ причины возникновения циклического обмена

Разберем ситуацию в отладчике, как это сделал автор темы. В современных конфигурациях, таких как БП 3.0, регистрация изменений для обмена данными часто реализована через подписки на события. Когда объект (справочник или документ) записывается в базу данных в процессе обмена, платформа устанавливает свойство ОбменДанными.Загрузка в значение Истина. Это должно сигнализировать всем обработчикам, что выполнять дополнительные проверки и действия (включая регистрацию изменений) не требуется.

Однако в некоторых случаях в общем модуле ОбменДаннымиСобытия или в самих подписках логика проверки модифицированности объекта может быть реализована таким образом, что регистрация выполняется безусловно. Это может быть связано с особенностями версии БСП или некорректной настройкой плана обмена в части авторегистрации объектов.

Проанализируем ситуацию: на каждый объект срабатывает подписка на событие (например, ПередЗаписью или ПриЗаписи). Если внутри этой подписки вызывается процедура регистрации, которая не проверяет ЭтотОбъект.ОбменДанными.Загрузка, объект попадает в очередь на выгрузку. Получается бесконечный цикл: УПП отправляет данные в БП, БП записывает их и тут же ставит в очередь на отправку обратно в УПП.

Решение 1: Программное удаление регистрации в обработчике «ПослеЗагрузкиДанных»

Если мы не можем изменить логику работы типовых подписок (например, из-за нежелания снимать конфигурацию с поддержки или из-за сложности структуры БСП), мы можем воспользоваться механизмом очистки регистрации сразу после завершения процесса загрузки. Для этого в правилах обмена (в обработчике ПослеЗагрузкиДанных) можно написать код, который принудительно удалит только что созданные записи из плана обмена.

Рассмотрим пример кода, который позволяет собрать все загруженные ссылки и одним махом очистить их регистрацию на конкретном узле обмена:


// Определяем узел обмена, для которого нужно удалить регистрацию
// В данном примере код узла указан явно ("002"), далее мы разберем, как сделать это динамически
Узел = ПланыОбмена.СинхронизацияДанныхЧерезУниверсальныйФормат.НайтиПоКоду("002");

МассивСсылок = Новый Массив;

// Проходим по коллекции загруженных объектов
Для Каждого ТекЭлемент Из ЗагруженныеОбъекты Цикл
    // Проверяем, что объект имеет ссылочный тип
    Если ОбщегоНазначения.ЭтоСсылка(ТипЗнч(ТекЭлемент.Значение.СсылкаНаОбъект)) Тогда
        МассивСсылок.Добавить(ТекЭлемент.Значение.СсылкаНаОбъект);
    КонецЕсли;
КонецЦикла;

// Удаляем регистрацию изменений для всего массива объектов за один вызов
// Это значительно быстрее, чем удалять регистрацию по одному объекту в цикле
ПланыОбмена.УдалитьРегистрациюИзменений(Узел, МассивСсылок);

Важный момент: использование метода ПланыОбмена.УдалитьРегистрациюИзменений с передачей массива ссылок является наиболее производительным способом. Это минимизирует количество обращений к таблицам регистрации изменений в базе данных.

Решение 2: Динамическое определение узла обмена

В предыдущем примере мы использовали жестко заданный код узла "002". Это плохая практика («хардкод»), так как при смене префиксов или создании новых настроек обмена код перестанет работать. Выясним, как получить ссылку на текущий узел обмена более корректно.

В обработчиках загрузки данных обычно доступен контекст, в котором выполняется обмен. Если вы используете универсальный обмен данными XML, ссылка на узел может содержаться в параметрах обработки. Посмотрим, как можно доработать код:


// Если мы находимся в контексте выполнения обмена через БСП
Узел = Параметры.УзелИнформационнойБазы;

// Если узел не определен в параметрах напрямую, можно попробовать найти его
// по типу плана обмена, используемого в текущей сессии
Если Узел = Неопределено Или Узел.Пустая() Тогда
    // Альтернативный поиск (требует осторожности при наличии нескольких обменов)
    // Узел = ... 
КонецЕсли;

Решение 3: Работа с регистрами и объектами без ссылок

Как справедливо было замечено в обсуждении, метод с массивом ссылок не сработает для регистров сведений, регистров накопления или констант, так как они не являются ссылочными типами данных. Для них регистрация изменений хранится по-другому.

Чтобы удалить регистрацию изменений для набора записей регистра, нам нужно использовать Структуру с отбором. Разберем пример для регистра сведений:


// Для регистров необходимо формировать отбор по ключевым полям (измерениям)
Для Каждого ТекЭлемент Из ЗагруженныеОбъекты Цикл
    ТипОбъекта = ТипЗнч(ТекЭлемент.Значение.СсылкаНаОбъект);
    
    // Проверка, является ли объект набором записей регистра
    Если Найти(Строка(ТипОбъекта), "НаборЗаписей") > 0 Тогда
        // Формируем отбор (в ТекЭлемент.Значение обычно содержится информация об измерениях)
        // Для каждого конкретного регистра структура отбора будет своя
        ПланыОбмена.УдалитьРегистрациюИзменений(Узел, ТипОбъекта, ТекЭлемент.Значение.Отбор);
    КонецЕсли;
КонецЦикла;

Однако более эффективным подходом для регистров в БП 3.0 является использование Правил регистрации объектов (ПРО).

Решение 4: Использование Правил регистрации объектов (ПРО)

Самый правильный и «чистый» способ решения проблемы циклического обмена — это настройка правил регистрации в конфигурации «Конвертация данных». В БП 3.0 (БСП) логика постановки объекта в очередь на выгрузку управляется именно этими правилами.

Рассмотрим, что нужно сделать в ПРО:

  1. Откройте ваши правила регистрации в конфигурации «Конвертация данных 2.0».
  2. Найдите правило для нужного объекта (например, справочника «Номенклатура»).
  3. В обработчике «Перед обработкой» или «При регистрации» добавьте проверку на источник изменения.
  4. Вы можете использовать проверку системного флага:
    
    Если ОбменДанными.Загрузка Тогда
        Отказ = Истина;
    КонецЕсли;
    

Если вы установите Отказ = Истина в правилах регистрации при условии, что идет загрузка, объект никогда не попадет в таблицу регистрации изменений, и проблема циклического обмена исчезнет сама собой без написания дополнительных процедур удаления.

Рекомендации по настройке авторегистрации

Проанализируем еще один важный аспект — настройки в Конфигураторе. У каждого плана обмена есть список входящих в него объектов. Для каждого объекта в свойстве «Авторегистрация» может стоять «Разрешить» или «Запретить».

Совет: Если вы сталкиваетесь с неконтролируемой регистрацией, рекомендуется установить «Авторегистрация» в значение «Запретить». В этом случае регистрация будет происходить только тогда, когда это явно прописано в программном коде или правилах регистрации. Это дает разработчику полный контроль над процессом и исключает «самодеятельность» платформы при записи объектов во время обмена.

Резюме

Для корректной настройки обмена УПП — БП 3.0 без зацикливания мы рекомендуем следующий алгоритм действий:

  1. Проверить правила регистрации (ПРО): Это наиболее приоритетный метод. Убедитесь, что в них прописан отказ от регистрации при Загрузка = Истина.
  2. Отключить авторегистрацию: В свойствах плана обмена в конфигураторе для проблемных объектов установите «Запретить».
  3. Программная очистка: Если первые два пункта невозможны, используйте оптимизированный код в обработчике ПослеЗагрузкиДанных для удаления регистрации изменений через массив ссылок.
  4. Внимание к регистрам: Помните, что для регистров требуется удаление через структуру отбора, а не через массив ссылок.

Следуя этим шагам, вы обеспечите стабильную работу синхронизации данных и избежите избыточной нагрузки на сервер, вызванной бесконечной пересылкой одних и тех же объектов между базами.

← На главную