Как программно определить успешное завершение обмена в РИБ для запуска постобработки?

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

При построении архитектуры распределенных информационных баз (РИБ) часто возникает задача организации последовательных цепочек обработки: сразу после того, как центральная база успешно загрузила пакет данных от периферийного узла, необходимо запустить постобработку полученной информации (например, актуализацию движений, проведение отложенных документов, расчет аналитических регистров или пересчет остатков). Рассмотрим, какие механизмы платформы 1С:Предприятие 8.3 и Библиотеки стандартных подсистем (БСП) позволяют надежно зафиксировать момент успешного окончания сеанса обмена данными.

Способ 1. Анализ служебных регистров сведений БСП

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

  1. СостоянияОбменовДанными — содержит актуальные данные о текущем статусе (выполняется, завершен с ошибками, завершен успешно), времени начала и окончания сеанса как для регламентных заданий, так и для ручных вызовов.
  2. СостоянияУспешныхОбменовДанными — хранит дату и время последней успешной выгрузки и загрузки по каждому узлу плана обмена.

Разберем, как получить статус завершения обмена запросом к регистру сведений. Посмотрим на пример кода проверки:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Состояния.РезультатВыполненияОбмена КАК Результат,
    |	Состояния.ДатаОкончания КАК ДатаОкончания
    |ИЗ
    |	РегистрСведений.СостоянияОбменовДанными КАК Состояния
    |ГДЕ
    |	Состояния.УзелИнформационнойБазы = &Узел
    |	И Состояния.ДействиеПриОбмене = &ДействиеПриОбмене";

Запрос.УстановитьПараметр("Узел", ВыбранныйУзелРИБ);
// Проверяем операцию загрузки данных
Запрос.УстановитьПараметр("ДействиеПриОбмене", Перечисления.ДействияПриОбмене.ЗагрузкаДанных);

РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
    Выборка = РезультатЗапроса.Выбрать();
    Выборка.Следующий();
    
    Если Выборка.Результат = Перечисления.РезультатыВыполненияОбмена.Выполнено Тогда
        // Обмен завершен успешно, запускаем обработку
    КонецЕсли;
КонецЕсли;

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

Способ 2. Проверка состояния фоновых заданий платформы

Когда синхронизация запускается по расписанию регламентным заданием, платформа выполняет код в отдельном изолированном потоке. Проанализируем состояние этого процесса с помощью менеджера фоновых заданий.

Метод ПолучитьСеансыИнформационнойБазы() возвращает коллекцию активных пользовательских и системных подключений:


Сеансы = ПолучитьСеансыИнформационнойБазы();
Для Каждого Сеанс Из Сеансы Цикл
    Если Сеанс.ИмяПриложения = "BackgroundJob" Тогда
        Фоновое = Сеанс.ПолучитьФоновоеЗадание();
        Если Фоновое <> Неопределено Тогда
            Сообщить("Задание: " + Строка(Фоновое.КраткоеОписание) + ", Состояние: " + Строка(Фоновое.Состояние));
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

Однако получение активных сеансов показывает только текущие подключения в реальном времени и не сохраняет историю уже закрытых потоков. Чтобы проверить результат выполнения завершенного задания, используем метод ПолучитьФоновыеЗадания() объекта ФоновыеЗадания. Свойство Состояние у объекта фонового задания принимает системные значения перечисления ФоновоеЗаданиеСостояние:

  1. Активно — обмен еще идет;
  2. Завершено — задание отработало успешно;
  3. ЗавершеноАварийно — в процессе возникло необработанное исключение;
  4. Отменено — задание прервано администратором или системой.

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

Способ 3. Контроль номера принятого сообщения узла

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

Ключевой критерий успешного завершения чтения пакета платформой — атомарное увеличение реквизита НомерПринятого у соответствующего узла плана обмена. Если во время чтения возникла синтаксическая или логическая ошибка, произошла коллизия блокировок или аварийное завершение, транзакция целиком откатывается, и значение НомерПринятого не увеличивается.

Рассмотрим алгоритм контроля:

  1. Сохраняем текущее значение Узел.НомерПринятого в константу или служебный регистр.
  2. При следующей проверке считываем текущее значение реквизита НомерПринятого из базы данных.
  3. Если значение увеличилось, значит, очередной входящий пакет от периферийной базы был физически и полностью записан в информационную базу.

Способ 4. Перехват события завершения через расширение (Push-модель)

Вместо постоянного циклического опроса статусов (Polling) надежнее инициировать постобработку по факту самого события. Начиная с платформы 8.3.9, доступен механизм расширений конфигурации с директивой &После.

Разберем шаги реализации:

  1. Находим в модуле ОбменДаннымиСервер (или в модуле менеджера соответствующего плана обмена) процедуру, завершающую выполнение сценария обмена данными.
  2. Подключаем расширение с аннотацией &После к процедуре завершения загрузки.
  3. В обработчике расширения проверяем признак успешного выполнения (отсутствие ошибок загрузки).
  4. При положительном результате вызываем метод ФоновыеЗадания.Выполнить(...), передавая туда процедуру обработки полученных данных. Запуск в фоновом задании позволяет сразу же освободить сеанс обмена и не затягивать транзакцию синхронизации.

Способ 5. Построение очереди отложенной обработки (Decoupling)

В высоконагруженных системах жесткая привязка «обмен завершился — сразу запускаем обработку» не всегда стабильна: следующий обмен может начаться раньше, чем закончится постобработка предыдущего, что приведет к взаимным блокировкам.

Наиболее масштабируемое решение — построение независимой очереди:

  1. В модуле плана обмена в процедуре ПриПолученииДанныхОтПодчиненного или через подписку на событие записи объектов перехватываем поступающие изменения.
  2. Записываем ссылки на загруженные документы или справочники в служебный регистр сведений (очередь обработки).
  3. Регламентное задание постобработки запускается независимо по собственному расписанию (например, раз в 5–10 минут), считывает порцию накопленных записей из регистра-очереди, обрабатывает их и удаляет записи из очереди.

Такой подход полностью устраняет зависимость от того, каким образом был запущен обмен (регламентом или вручную), гарантирует обработку всех входящих данных и исключает конфликты блокировок между процессами обмена и бизнес-логики.

← На главную