Чёрный пояс 1С. РИБ на нестабильной связи: как не отправлять сканы договоров в каждое сообщение обмена
Периферийная нефтебаза, связь через раз, а сообщение обмена РИБ весит триста мегабайт — потому что кто-то прикрепил скан договора во внешнюю табличную часть, и платформа честно сериализовала его в XML. Канал захлёбывается, узел отстаёт от центра на дни. И это ещё до того, как вы столкнётесь с обновлением структуры метаданных на живом филиале.
Легенда практического занятия
Связь между центральным офисом и периферийными узлами РИБ нестабильна. Документы содержат сканы договоров во внешней табличной части, из-за чего сообщения обмена разрастаются до сотен мегабайт. Плановые обновления структуры метаданных при этом блокируют работу филиалов на часы.
Задание
- Напишите обработчик
ПриОтправкеДанныхПодчиненному, исключающий тяжёлый реквизитФайлСканаиз выгрузки для справочникаДоговорыКонтрагентов. - Опишите стандартный алгоритм разрешения коллизий по умолчанию в иерархии «главный - подчинённый».
- Разработайте алгоритм подчинённого узла, который безопасно прерывает чтение сообщения при обнаружении изменений метаданных.
1. Фильтрация тяжёлых данных на отправке
Процедура ПриОтправкеДанныхПодчиненному(ЭлементДанных, ОтправкаЭлементаДанных)
// Проверяем тип отправляемого объекта
Если ТипЗнч(ЭлементДанных) = Тип("СправочникОбъект.ДоговорыКонтрагентов") Тогда
// Если скан-копия заполнена, исключаем отправку элемента или модифицируем его
Если ЭлементДанных.ФайлСкана.Получить() <> Неопределено Тогда
// Вариант 1: Полный пропуск отправки тяжелого объекта
ОтправкаЭлементаДанных = ОтправкаЭлементаДанных.Игнорировать;
// Вариант 2: Сброс тяжелого реквизита перед сериализацией
// ЭлементДанных.ФайлСкана = Новый ХранилищеЗначений(Неопределено);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Игнорировать вообще не отправляет элемент в этой сессии обмена (регистрация изменений сохранится для следующей отправки, когда канал будет шире), а сброс реквизита отправляет сам элемент, но без тяжёлого файла — подчинённый узел получит договор со всеми полями, кроме скана. Выбор зависит от того, нужен ли скан на периферии вообще, или это чисто центральный архив.2. Кто побеждает в коллизии
Платформа разрешает коллизии по умолчанию по простому правилу приоритета: главный узел всегда выигрывает.
- Сообщение от подчинённого узла: если изменённый элемент данных уже зарегистрирован к обмену в текущем (главном) узле — это коллизия. Платформа игнорирует изменение подчинённого, не записывает его в базу, а регистрация изменений для подчинённого узла сохраняется — чтобы при следующей отправке подчинённый получил актуальную версию от главного.
- Сообщение от главного узла: изменение имеет безусловный приоритет. Оно записывается в базу подчинённого узла без вопросов, а регистрация изменений для главного узла на подчинённом удаляется.
3. Безопасное горячее обновление подчинённого узла
// Процедура автоматического разбора сообщения обмена в подчиненном узле
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ИмяФайлаСообщения);
ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();
ЧтениеСообщения.НачатьЧтение(ЧтениеXML);
// Анализ заголовка сообщения без чтения тела бизнес-данных
ОписаниеИзменений = ПланыОбмена.ПрочитатьИзмененияКонфигурацииИРасширенийКонфигурации(ЧтениеСообщения);
Если ОписаниеИзменений.КонфигурацияИзменена Тогда
// Изменение метаданных в главном узле требует реструктуризации БД в подчиненном
ВызватьИсключение "ТребуетсяОбновлениеКонфигурации"; // Выход для монопольного обновления в конфигураторе
ИначеЕсли ОписаниеИзменений.РасширенияКонфигурацииИзменены Тогда
ВызватьИсключение "ТребуетсяПерезапуск";
ИначеЕсли ОписаниеИзменений.ИзмененныеМетаданныеРасширенийКонфигурацииИзменяютСтруктуруДанных Тогда
// Монопольная блокировка для применения расширений, меняющих структуру таблиц СУБД
УстановитьМонопольныйРежим(Истина);
КонецЕсли;
// Если структура конфигурации идентична, продолжаем чтение данных
ПланыОбмена.ПрочитатьИзменения(ЧтениеСообщения);
ЧтениеСообщения.ЗакончитьЧтение();
ЧтениеXML.Закрыть();
Ключевой архитектурный приём — читать заголовок сообщения до чтения тела бизнес-данных. Это позволяет обнаружить изменение структуры метаданных и безопасно прервать процесс, не начиная запись документов в базу со старой структурой. Изменения конфигурации всегда вносятся в корневом узле РИБ — подчинённый узел только принимает их и применяет локально.
Что проверить у себя на проекте
- Есть ли фильтрация тяжёлых вложений в событиях отправки хотя бы для трёх-четырёх самых частых типов документов с файлами — обычно это 90% объёма трафика РИБ.
- Знают ли пользователи филиалов о правиле приоритета главного узла — иначе потерянные правки будут восприниматься как баг платформы, а не следствие архитектуры.
- Проверяет ли ваш код заголовок сообщения на изменение структуры до чтения бизнес-данных, а не после — порядок здесь определяет, будет авария на приёме контролируемой или нет.
Создать токен →