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