Как правильно организовать асинхронную выгрузку на FTP при записи документа в 1С?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

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

Почему возникают ошибки при асинхронном запуске?

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

Решение 1: Использование регистра сведений (Очередь заданий)

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

  1. Создаем РегистрСведений (например, «ОчередьВыгрузкиНаFTP»).
  2. В подписке на событие ПослеЗаписи объекта записываем в этот регистр ссылку на документ и признак «Готов к отправке».
  3. Настраиваем РегламентноеЗадание, которое работает по расписанию, опрашивает этот регистр и выполняет выгрузку.

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

Решение 2: Проверка готовности внутри фонового задания

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

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


Процедура ВыполнитьВыгрузку(СсылкаНаДокумент, НоваяВерсияДанных) Экспорт
    КоличествоПопыток = 0;
    Пока Истина Цикл
        // Добавляем искусственную паузу, чтобы дать транзакции завершиться
        ОбъектРасширения.Спать(1000); 
        
        ТекущаяВерсияДанных = ПолучитьВерсиюДанных(СсылкаНаДокумент);
        
        // Если версия совпадает, значит документ успешно записан
        Если ТекущаяВерсияДанных = НоваяВерсияДанных Тогда
            ВыполнитьВыгрузкуНаFTP(СсылкаНаДокумент);
            Прервать;
        КонецЕсли;
        
        КоличествоПопыток = КоличествоПопыток + 1;
        Если КоличествоПопыток > 5 Тогда
            ЗаписатьВЖурнал("Ошибка: превышено время ожидания записи");
            Возврат;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Решение 3: Ожидание завершения через метод платформы

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


// Получаем фоновое задание по наименованию и ждем его завершения
СписокЗаданий = ФоновыеЗадания.ПолучитьФоновыеЗадания(Новый Структура("Наименование", "Выгрузка заказ"));
Если СписокЗаданий.Количество() > 0 Тогда
    СписокЗаданий[0].ОжидатьЗавершения(60); // Ждем до 60 секунд
КонецЕсли;

Итоговые рекомендации по архитектуре

Разберем основные принципы, которые помогут вам избежать проблем:

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

← На главную