Как отловить завершение выполнения регламентного задания в 1С без изменения конфигурации

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

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

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

---

Способ 1. Использование подписки на события регистра сведений

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

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

Разберем реализацию этого способа по шагам:

  1. Создадим новый общий модуль в нашей конфигурации (например, _МойСлужебныйСобытияСервер). В свойствах модуля обязательно установим флаги Сервер и Внешнее соединение.
  2. Создадим новый объект метаданных Подписка на событие (например, _ОтследитьЗавершениеОбмена).
  3. В свойствах созданной подписки укажем:
    • Источник: РегистрСведенийНаборЗаписей.УспешныеОбменыССайтом (или тот регистр, который отвечает за статус завершения вашего обмена).
    • Событие: ПриЗаписи.
    • Обработчик: выберем процедуру из нашего общего модуля _МойСлужебныйСобытияСервер.ПриЗаписиСтатусаОбмена.

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


Процедура ПриЗаписиСтатусаОбмена(Источник, Отказ, Замещение) Экспорт

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

КонецПроцедуры

Преимущества метода: полная независимость от кода самого регламентного задания. Метод работает на уровне СУБД при фиксации транзакции записи данных.

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

---

Способ 2. Расширение конфигурации и аннотация &После

Если используемая версия платформы "1С:Предприятие" поддерживает механизм расширений (рекомендуется 8.3.10 и выше), то этот метод является наиболее современным, чистым и предпочтительным.

Суть метода заключается в перехвате выполнения процедуры общего модуля, которую вызывает регламентное задание, с помощью аннотации &После (&After).

Разберем алгоритм настройки расширения:

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

Рассмотрим пример кода в модуле расширения:


&После("ВыполнитьОбменДанными")
Процедура Расш1_ВыполнитьОбменДанными(ПараметрыОбмена)
    
    // Этот код гарантированно выполнится в том же фоновом сеансе
    // сразу после успешного завершения основной процедуры обмена.
    
    Попытка
        // Вызываем логику нашей кастомной обработки из собственного модуля
        МойМодульПостобработки.ВыполнитьДействияПослеОбмена();
        
        ЗаписьЖурналаРегистрации("МониторингОбмена.Постобработка",
            УровеньЖурналаРегистрации.Информация,
            ,
            ,
            "Постобработка обмена успешно завершена.");
    Исключение
        // Обязательно обрабатываем ошибки, чтобы авария в нашей логике 
        // не привела к ложному флагу сбоя самого обмена, если это критично
        ЗаписьЖурналаРегистрации("МониторингОбмена.Постобработка",
            УровеньЖурналаРегистрации.Ошибка,
            ,
            ,
            ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;

КонецПроцедуры

Преимущества метода: код выполняется строго в контексте фонового задания обмена, у вас есть доступ ко всем локальным переменным и параметрам, переданным в оригинальный метод. Основная конфигурация остается на 100% типовой.

---

Способ 3. Создание регламентного задания-«обертки» (Wrapper)

Если применение расширений по каким-то причинам ограничено политикой безопасности компании, но создавать новые объекты в основной конфигурации разрешено, мы можем применить паттерн "Обертка".

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

Разберем по шагам, как это реализовать:

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

Напишем код для нашего метода-обертки:


Процедура ВыполнитьОбменИПостобработку() Экспорт
    
    // Шаг 1. Программный запуск оригинального метода обмена
    Попытка
        // Вызываем экспортируемую процедуру оригинального общего модуля
        ОбменССайтомСлужебный.ВыполнитьОбменДанными();
    Исключение
        // Фиксируем ошибку оригинального обмена
        ЗаписьЖурналаРегистрации("МойОбмен.Ошибка",
            УровеньЖурналаРегистрации.Ошибка,
            ,
            ,
            "Ошибка при выполнении основного обмена: " + ОписаниеОшибки());
            
        // Прерываем выполнение, так как обмен завершился аварийно
        ВызватьИсключение "Основной обмен завершился с ошибкой. Постобработка отменена.";
    КонецПопытки;
    
    // Шаг 2. Выполнение нашей кастомной логики
    Попытка
        МойМодульПостобработки.ВыполнитьДействияПослеОбмена();
    Исключение
        ЗаписьЖурналаРегистрации("МойОбмен.ОшибкаПостобработки",
            УровеньЖурналаРегистрации.Ошибка,
            ,
            ,
            "Ошибка при выполнении постобработки: " + ОписаниеОшибки());
    КонецПопытки;

КонецПроцедуры

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

---

Способ 4. Программный мониторинг фоновых заданий (Polling)

Этот способ незаменим, когда запуск обмена происходит асинхронно, интерактивно пользователем из формы или нам необходимо отследить завершение процесса на стороне клиента (в интерфейсе).

Платформа "1С:Предприятие" предоставляет мощный программный интерфейс для работы с активными процессами через менеджер ФоновыеЗадания.

Рассмотрим пример реализации на клиенте с использованием обработчика ожидания:


&НаКлиенте
Перем ИдентификаторФоновогоЗадания;

&НаКлиенте
Процедура ЗапуститьМониторингОбмена(IDЗадания)
    
    ИдентификаторФоновогоЗадания = IDЗадания;
    
    // Подключаем ежесекундную проверку состояния фонового процесса
    ПодключитьОбработчикОжидания("ПроверитьСтатусВыполненияОбмена", 2, Ложь);
    
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьСтатусВыполненияОбмена()
    
    СостояниеЗадания = ПолучитьСостояниеЗаданияНаСервере(ИдентификаторФоновогоЗадания);
    
    Если СостояниеЗадания = "Активно" Тогда
        // Задание еще выполняется, продолжаем ожидать
        Возврат;
    Иначе
        // Процесс завершился, отключаем таймер
        ОтключитьОбработчикОжидания("ПроверитьСтатусВыполненияОбмена");
        
        Если СостояниеЗадания = "Завершено" Тогда
            ПоказатьПредупреждение(, "Обмен успешно завершен! Данные обновлены.");
            // Выполняем действия на клиенте после обмена
        Иначе
            ПоказатьПредупреждение(, "В процессе обмена произошла ошибка!");
        EndIf;
    КонецЕсли;
    
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьСостояниеЗаданияНаСервере(Идентификатор)
    
    Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(Идентификатор);
    Если Задание = Неопределено Тогда
        Возврат "НеНайдено";
    КонецЕсли;
    
    Возврат Строка(Задание.Состояние);
    
КонецФункции

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

---

Резюме и рекомендации

Мы подробно разобрали различные архитектурные подходы к отслеживанию окончания работы регламентных заданий в "1С:Предприятии". Выбор конкретного метода зависит от технических условий проекта:

← На главную