Почему регламентное задание в 1С выполняется без ошибок, но не изменяет объекты?

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

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

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

Анализ исходного кода и первая диагностика

Для начала рассмотрим типичный пример кода, который часто пишется для подобных задач. Предположим, нам необходимо обойти справочник Номенклатура и удалить из наименований всех элементов техническую приставку "удалить".


Процедура ВыполнитьОбработку() Экспорт
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ
                   |    СправочникНоменклатура.Ссылка КАК Ссылка
                   |ИЗ
                   |    Справочник.Номенклатура КАК СправочникНоменклатура
                   |ГДЕ
                   |    СправочникНоменклатура.Наименование ПОДОБНО ""%удалить%""";
    Выборка = Запрос.Выполнить().Выбрать();
    Пока Выборка.Следующий() Цикл
        Если ЗначениеЗаполнено(Выборка.Ссылка) Тогда
            ОбъектНоменклатура = Выборка.Ссылка.ПолучитьОбъект();
            ОбъектНоменклатура.Наименование = СтрЗаменить(ОбъектНоменклатура.Наименование, "удалить", "");
            ОбъектНоменклатура.Записать();
        КонецЕсли;    
    КонецЦикла;        
КонецПроцедуры

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

  1. Использование ключевого слова РАЗЛИЧНЫЕ в данном запросе избыточно, так как поле Ссылка справочника по определению уникально.
  2. Проверка ЗначениеЗаполнено(Выборка.Ссылка) внутри цикла обхода результата запроса не имеет практического смысла. Запрос к реальной таблице справочника не может вернуть пустую или битую ссылку в выборке (если только не используются левые соединения с другими таблицами).

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

Причина 1. Различие контекстов выполнения (Клиент / Сервер)

Это самая распространенная причина "тихого" невыполнения кода. Регламентные задания 1С всегда выполняются исключительно на сервере в контексте фонового сеанса. При ручном запуске обработки код чаще всего стартует в контексте клиента (в толстом или тонком клиенте), после чего управление может передаваться на сервер.

При вызове метода ОбъектНоменклатура.Записать() платформа последовательно запускает транзакционные события модуля объекта: ПередЗаписью и ПриЗаписи. Также срабатывают подписки на события, зарегистрированные в конфигурации для данного типа объекта.

Проанализируем следующую ситуацию: в обработчике ПередЗаписью или ПриЗаписи модуля объекта справочника Номенклатура разработчик (или типовой механизм конфигурации) вызывает процедуру из общего модуля. Если у этого общего модуля в свойствах не установлена галочка "Сервер" (а установлена, например, только "Клиент (управляемое приложение)" или "Толстый клиент"), серверный процесс фонового задания просто не сможет скомпилировать этот участок кода.

В некоторых случаях это приводит к падению фонового задания с ошибкой, но если вызов обернут в неявную конструкцию Попытка ... Исключение внутри типовых библиотек, ошибка будет "проглочена". Транзакция записи отменится, изменения не сохранятся, а само регламентное задание завершится со статусом успешного выполнения.

Решение: Проверить все подписки на события записываемого объекта и процедуры модуля объекта ПередЗаписью / ПриЗаписи. Убедиться, что все вызываемые в них общие модули имеют признак выполнения на сервере.

Причина 2. Ограничение прав доступа и механизм RLS

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

Если пользователь для регламентного задания не задан, или у назначенного пользователя ограничены права (например, настроен механизм RLS — Restriction on Level of Records), поведение системы резко меняется:

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

Рассмотрим, как правильно доработать код:


Процедура ВыполнитьОбработку() Экспорт
    
    // Включаем привилегированный режим для обхода RLS и проверок прав
    УстановитьПривилегированныйРежим(Истина);
    
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
                   |    СправочникНоменклатура.Ссылка КАК Ссылка
                   |ИЗ
                   |    Справочник.Номенклатура КАК СправочникНоменклатура
                   |ГДЕ
                   |    СправочникНоменклатура.Наименование ПОДОБНО ""%удалить%""";
                   
    Выборка = Запрос.Выполнить().Выбрать();
    
    Пока Выборка.Следующий() Цикл
        
        ОбъектНоменклатура = Выборка.Ссылка.ПолучитьОбъект();
        ОбъектНоменклатура.Наименование = СтрЗаменить(ОбъектНоменклатура.Наименование, "удалить", "");
        
        Попытка
            ОбъектНоменклатура.Записать();
        Исключение
            // Обязательно фиксируем возможные ошибки записи в Журнал регистрации
            ЗаписьЖурналаРегистрации("РегламентныеЗадания.ОшибкаЗаписи",
                УровеньЖурналаРегистрации.Ошибка,
                ОбъектНоменклатура.Метаданные(),
                ОбъектНоменклатура.Ссылка,
                ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
        КонецПопытки;
        
    КонецЦикла;        
    
КонецПроцедуры

Причина 3. Интерактивные методы в серверном коде

Часто в логику объектов (модули справочников, документов) встраивают вызовы функций, которые требуют взаимодействия с пользователем. Например:

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

Решение: Обернуть все интерактивные вызовы в директивы компиляции или условия проверки контекста выполнения. Например, использовать проверку:

#Если Клиент Тогда или проверять системные параметры выполнения, чтобы не вызывать диалоговые окна при фоновой работе системы.

Методика пошаговой отладки фонового задания

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

Шаг 1. Использование Журнала регистрации для трассировки

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


ЗаписьЖурналаРегистрации("РегламентноеЗадание.Старт", УровеньЖурналаРегистрации.Информация,,, "Запуск обработки.");

Выборка = Запрос.Выполнить().Выбрать();
ЗаписьЖурналаРегистрации("РегламентноеЗадание.Запрос", УровеньЖурналаРегистрации.Информация,,, "Запрос выполнен. Количество записей: " + Выборка.Количество());

Пока Выборка.Следующий() Цикл
    ЗаписьЖурналаРегистрации("РегламентноеЗадание.Цикл", УровеньЖурналаРегистрации.Информация,,, "Обработка ссылки: " + Выборка.Ссылка);
    // Код записи объекта...
КонецЦикла;

ЗаписьЖурналаРегистрации("РегламентноеЗадание.Финиш", УровеньЖурналаРегистрации.Информация,,, "Обработка завершена.");

После выполнения задания откроем Журнал регистрации в режиме 1С:Предприятие и проанализируем созданные записи. Если в логах есть событие "Запрос" со значением "Количество записей: 0", значит, проблема в условиях запроса или ограничениях прав (RLS). Если логи обрываются или содержат ошибки внутри цикла — мы локализуем конкретный проблемный элемент номенклатуры.

Шаг 2. Настройка отладки фоновых заданий

Для того чтобы зайти отладчиком в код, выполняемый регламентным заданием на сервере, выполним следующие настройки:

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

Используя этот подход, мы сможем детально отследить по шагам весь процесс записи объекта и обнаружить, в какой именно момент (например, при вызове подписки на событие или общего модуля) происходит сброс транзакции записи.

← На главную