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

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

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

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

Причина, по которой исключение не фиксируется как ошибка

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

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

  1. Ваше исключение срабатывает.
  2. Системный код БСП перехватывает его.
  3. Ошибка записывается в Журнал регистрации (его можно выгрузить в Excel с группировкой для удобства изучения).
  4. Сама процедура-обертка завершается штатно, так как исключение было обработано.
  5. Платформа видит успешное завершение потока и ставит статус «Выполнено».

Рассмотрим подробнее, как обойти это поведение и какие альтернативы существуют (включая внешний регламент для 1С, работающий вне рамок БСП).

Способ 1. Проверка вложенных блоков исключений

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

Посмотрим на пример кода, который не позволит заданию завершиться аварийно:


Процедура ВыполнитьЗагрузкуДанных() Экспорт
    Попытка
        // Логика получения данных
        Если Данные.Количество() = 0 Тогда
             ВызватьИсключение "Данные не найдены";
        КонецЕсли;
    Исключение
        // Здесь ошибка перехвачена, но никак не проброшена выше
        ЗаписатьВЖурналРегистрации("Загрузка", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
    КонецПопытки;
КонецПроцедуры

Чтобы задание завершилось со статусом «Ошибка», необходимо либо убрать блок Попытка...Исключение, либо повторно вызвать исключение внутри блока Исключение с помощью ключевого слова ВызватьИсключение без параметров:


Исключение
    ЗаписатьВЖурналРегистрации("Загрузка", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
    ВызватьИсключение; // Пробрасываем ошибку на уровень платформы
КонецПопытки;

Способ 2. Использование критических ошибок без категорий

В платформе 8.3.23 и выше появился расширенный синтаксис исключений с категориями. Выясним, как это влияет на регламентные задания. Если вы используете КатегорияОшибки.ОшибкаВнешнегоИсточникаДанных, платформа может интерпретировать это как некритичную ошибку связи, которую не всегда нужно фиксировать как крах процесса.

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


Если Данные.Количество() = 0 Тогда
    // Используем классический вариант без дополнительных параметров
    ВызватьИсключение "Критическая ошибка: Данные из внешней базы не получены!";
КонецЕсли;

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

Способ 3. Реализация логики повтора через константу

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

Выполним следующие шаги:

  1. Создадим константу ДатаСледующейЗагрузки (тип Дата).
  2. Настроим регламентное задание на ежедневный запуск (например, каждый час или каждое утро).
  3. В начале кода задания добавим проверку.

Проанализируем пример реализации:


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

    Данные = ПолучитьДанныеИзВнешнейБазы();

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

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

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

Способ 4. Программное управление расписанием

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

Для этого используется объект РегламентныеЗадания. Посмотрим на пример кода:


МетаданныеЗадания = Метаданные.РегламентныеЗадания.ЗагрузкаИзВнешнейБазы;
Задание = РегламентныеЗадания.НайтиПоМетаданным(МетаданныеЗадания)[0];

Если ДанныеПолучены Тогда
    // Устанавливаем расписание: Раз в месяц, 1-го числа
    НовоеРасписание = Новый РасписаниеРегламентногоЗадания;
    НовоеРасписание.ПериодичностьЗавершенияВТечениеДня = 0;
    НовоеРасписание.ДеньВМесяце = 1;
    Задание.Расписание = НовоеРасписание;
    Задание.Записать();
Иначе
    // Устанавливаем расписание: Повторять каждые 30 минут, пока не получим данные
    НовоеРасписание = Новый РасписаниеРегламентногоЗадания;
    НовоеРасписание.ПериодичностьПовтораВТечениеДня = 1800; 
    Задание.Расписание = НовоеРасписание;
    Задание.Записать();
КонецЕсли;

Этот метод требует прав на управление регламентными заданиями у пользователя, под которым запускается фоновый процесс (обычно это учетная запись сервера 1С), но он является наиболее «профессиональным» с точки зрения эксплуатации системы.

Итоги и рекомендации

Мы выяснили, что отсутствие статуса «Ошибка» при вызове исключения чаще всего связано с перехватом этого исключения в вышестоящих модулях (особенно в типовых конфигурациях на базе БСП). Для решения задачи рекомендуем следующее:

Выбор конкретного метода зависит от того, насколько критично для вас видеть статус «Ошибка» в стандартной консоли регламентных заданий. Для стабильных промышленных систем использование управляемой логики (через даты запуска) всегда предпочтительнее, чем использование механизмов аварийного завершения.

← На главную