Надо понимать, что при вводе новых объектов в различных узлах обмена ссылки на объекты базы данных будут разными и все новые объекты будут «доставлены по назначению». Но при обмене уже существующими объектами базы данных (с одинаковыми ссылками), которые был изменены сразу в нескольких узлах обмена после последнего сеанса обмена, может возникнуть коллизия, когда требуется определить, какие изменения принять, а какие – отклонить.
Чтобы разрешить эту коллизию, в нашем примере мы будем использовать наиболее простую стратегию «главный – подчиненный». Согласно этой стратегии изменения, полученные от узла обмена, отмеченного в списке узлов как главный, будут иметь приоритет над остальными.
То есть если для одного и того же объекта обмена данными изменения будут зарегистрированы и в главном, и в любом другом узле обмена, то изменения главного узла будут приняты, а остальные – отклонены.
В процедуру ПрочитатьСообщенияСИзменениями() в модуле плана обмена (см. листинг 3.61) внесем следующие изменения (листинг 3.72).
Листинг 3.72. Процедура «ПрочитатьСообщениеСИзменениями»
Процедура ПрочитатьСообщениеСИзменениями() Экспорт
…
// Прочитать данные из сообщения в цикле. *** XML-сериализация.
Пока ОбменСУдаленнымиСкладами.ВозможностьЧтенияДанных(ЧтениеXML) Цикл
// Прочитать очередное значение.
Данные = ОбменСУдаленнымиСкладами.ПрочитатьДанные(ЧтениеXML);
// Проверить, нужно ли принимать сообщение от узла-отправителя. Если нет, отклонить изменения.
Если Не ОбменСУдаленнымиСкладами.ПринятьИзменения(ЧтениеСообщения.Отправитель, Данные) Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = Строка(Данные.Метаданные()) + ": " + Строка(Данные) + " – Изменения отклонены";
Сообщение.Сообщить();
Продолжить;
КонецЕсли;
// Записать полученные данные.
Данные.ОбменДанными.Отправитель = ЧтениеСообщения.Отправитель;
Данные.ОбменДанными.Загрузка = Истина;
Данные.Записать();
КонецЦикла;
КонецЦикла;
…
КонецПроцедуры
Добавленный фрагмент выделен жирным шрифтом. В этом фрагменте в цикле мы выполняем чтение данных, содержащихся в сообщении обмена.
Перед тем как записать данные в базу узла, в функции ПринятьИзменения(), расположенной в общем модуле ОбменСУдаленнымиСкладами (см. листинг 3.73), проверяется возможность принятия изменений от узла-отправителя сообщения. В параметре Данные в функцию передается полученный объект обмена, а в параметре Отправитель – ссылка на узел-отправитель сообщения.
Листинг 3.73. Функция для разрешения коллизии при обмене данными
Функция ПринятьИзменения(Отправитель, Данные)
Прием = Истина;
// Проверить зарегистрировано ли изменение данных для отправителя.
Если ПланыОбмена.ИзменениеЗарегистрировано(Отправитель, Данные) Тогда
// Разрешить получение данных только от главного узла.
Если Не Отправитель.Главный Тогда
Прием = Ложь;
КонецЕсли;
КонецЕсли;
Возврат Прием;
КонецФункции
С помощью метода менеджера планов обмена ИзменениеЗарегистрировано() мы проверяем, зарегистрировано ли изменение объекта для узла-отправителя в нашей базе данных. Если да и если отправитель не является главным узлом, мы отклоняем полученные изменения (возвращается Ложь). Во всех остальных случаях изменения принимаются (возвращается Истина).
На самом деле алгоритм принятия изменений, реализованный в функции ПринятьИзменения(), может быть другим, гораздо более сложным и нестандартным. Но мы показали только самый простой и очевидный пример разрешения коллизии.