Работа с регламентными заданиями в 1С:Предприятие часто преподносит сюрпризы, особенно когда речь идет о длительных операциях выгрузки данных в сторонние системы. Одной из наиболее запутанных ситуаций является «тихий» сбой: Журнал регистрации рапортует об успешном завершении задания, но по факту в конечном файле XML отсутствуют целые блоки данных (например, определенные периоды или группы записей). При этом ручной запуск той же самой обработки отрабатывает без нареканий.
В данной статье мы подробно разберем, почему возникают подобные аномалии, как организовать надежную диагностику и какие архитектурные подходы гарантируют стабильную выгрузку больших объемов информации.
Разберем ситуацию, которая часто встречается в реальной практике. Если у вас на сервере развернута копия основной базы (для тестов, отчетов или разработки), в ней по умолчанию могут быть включены те же регламентные задания, что и в «проде». Проанализируем, что происходит в этом случае:
rphost может аварийно завершить поток записи, из-за чего файл XML остается «обрезанным» (без закрывающих тегов), но статус задания в Журнале регистрации помечается как «Выполнено», если ошибка произошла на уровне файловой системы в финальный момент закрытия потока.Решение: Всегда отключайте регламентные задания в копиях информационных баз. Проверим программный способ защиты: добавим в начало модуля регламентного задания проверку на имя сервера или путь к базе данных. Рассмотрим пример кода:
Процедура ВыполнитьВыгрузкуДанных()
СтрокаСоединения = СтрокаСоединенияИнформационнойБазы();
Если Найти(Врег(СтрокаСоединения), "SERVER_PRODUCTION") = 0 Тогда
ЗаписьЖурналаРегистрации("ВыгрузкаДанных", УровеньЖурналаРегистрации.Предупреждение, , , "Запуск в копии базы отменен.");
Возврат;
КонецЕсли;
// Далее идет основная логика выгрузки
КонецПроцедуры
Если проблема не в копиях, нам потребуется «тяжелая артиллерия». Обычный Журнал регистрации может не фиксировать падения рабочих процессов сервера. Рассмотрим, как настроить инструменты мониторинга.
Во-первых, проанализируем состояние рабочих процессов rphost. При выгрузке огромных файлов XML (гигабайты данных) потребление памяти может превысить допустимые лимиты, установленные в консоли кластера. В этом случае сервер 1С принудительно перезапускает процесс. Для отслеживания таких событий настроим Технологический журнал (файл logcfg.xml) на событие EXCP (исключительные ситуации) и PROC (завершение процессов):
<log location="C:\1C_Logs" history="72">
<event>
<eq property="Name" value="EXCP"/>
</event>
<event>
<eq property="Name" value="PROC"/>
</event>
<property name="all"/>
</log>
Во-вторых, создадим собственное «текстовое логирование». Это позволит нам увидеть реальный прогресс выполнения задания в режиме реального времени. Посмотрим на пример реализации логирования в отдельный файл:
ТекстЛога = Новый ТекстовыйДокумент;
ТекстЛога.ДобавитьСтроку("" + ТекущаяДата() + ": Начало выгрузки.");
// ... выборка данных ...
ТекстЛога.ДобавитьСтроку("" + ТекущаяДата() + ": Выбрано записей: " + КоличествоЗаписей);
ТекстЛога.Записать("C:\Logs\export_log.txt");
Рекомендуется записывать метки времени через каждые 10 000 — 50 000 итераций. Если выгрузка прервется, по последней записи в текстовом логе мы поймем, на каком именно этапе произошел сбой.
Частой ошибкой программистов является формирование всего XML-документа в одной строковой переменной или использование объекта ДокументDOM для очень больших объемов данных. Это гарантированный путь к переполнению оперативной памяти.
Рассмотрим правильный подход с использованием объекта ЗаписьXML. Этот объект выполняет потоковую запись данных непосредственно на диск, не накапливая весь текст в памяти 1С. Проанализируем структуру кода:
Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл(ПутьКФайлу, "UTF-8");
Запись.ЗаписатьОбъявлениеXML();
Запись.ЗаписатьНачалоЭлемента("Root");
Выборка = РегистрыСведений.НазваниеРегистра.Выбрать(ДатаНачала, ДатаКонца);
Пока Выборка.Следующий() Цикл
Запись.ЗаписатьНачалоЭлемента("Item");
Запись.ЗаписатьАтрибут("Period", Формат(Выборка.Период, "ДФ=yyyy-MM-dd"));
// Запись остальных данных
Запись.ЗаписатьКонецЭлемента(); // Item
КонецЦикла;
Запись.ЗаписатьКонецЭлемента(); // Root
Запись.Закрыть();
Важный момент: использование конструкции Попытка...Исключение вокруг всего цикла выгрузки обязательно. В блоке Исключение необходимо принудительно вызывать Запись.Закрыть(), иначе файл останется заблокированным процессом даже после ошибки.
Если внешняя система (приемник данных) настроена на автоматическое считывание файла при его появлении, может возникнуть ситуация, когда 1С еще пишет данные, а Qlik уже пытается их прочитать. Это приводит к блокировке файла и неполной выгрузке.
Разберем стратегию «Временного файла», которая считается стандартом в промышленной разработке:
.tmp (например, data_2023.xml.tmp).Запись.Закрыть(), когда файл гарантированно сформирован и освобожден 1С, выполняем переименование файла в целевой (data_2023.xml).Для переименования используем метод ПереместитьФайл():
ИмяФайлаВременное = "C:\Export\data.xml.tmp";
ИмяФайлаИтоговое = "C:\Export\data.xml";
// ... процесс выгрузки в ИмяФайлаВременное ...
ПереместитьФайл(ИмяФайлаВременное, ИмяФайлаИтоговое);
Для еще большей надежности можно использовать механизм «файлов-флагов». Рассмотрим эту методику: после успешной выгрузки 1С создает в папке пустой файл с именем success.txt. Система-приемник начинает обработку только при наличии этого файла, а после завершения чтения — удаляет его. Регламентное задание 1С перед началом новой выгрузки проверяет отсутствие флага. Если флаг еще существует, значит, предыдущая порция данных не обработана или процесс завис, и запуск стоит отложить.
Проанализируем преимущества этого метода:
Подводя итог, отметим, что «сбои» регламентных заданий редко бывают случайными. Чаще всего это следствие нехватки ресурсов (памяти), конфликтов доступа или отсутствия проверок на среду выполнения (продуктив/копия). Используя потоковую запись через ЗаписьXML, настраивая технологический журнал и внедряя схему с временными файлами, мы можем добиться стопроцентной стабильности интеграционных процессов.