Как выполнить длительную операцию при записи документа в 1С, не блокируя работу пользователя

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

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

Проблема синхронного выполнения в транзакции

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

Решение через фоновые задания БСП

Библиотека стандартных подсистем (БСП) предоставляет мощный инструментарий для работы с длительными операциями. Наиболее правильный путь — запустить фоновое задание, которое выполнит обмен с веб-сервисом «в фоне», пока пользователь продолжает работу с программой. Рассмотрим подробнее, как это реализовать, если мы хотим внести минимум изменений в типовую конфигурацию.

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

  1. Создадим новое расширение конфигурации.
  2. Добавм в него новый общий модуль (например, _ИнтеграцияВнешнийСервис) с установленными флажками "Сервер" и "Вызов сервера".
  3. В этом модуле разместим экспортную процедуру, которая будет выполнять работу с веб-сервисом.

Посмотрим на пример кода такой процедуры:


Процедура ВыполнитьОбменССервисом(ПараметрыЗадания, АдресРезультата = "") Экспорт
    
    СсылкаНаДокумент = ПараметрыЗадания.Ссылка;
    ДанныеДляОтправки = ПараметрыЗадания.Данные;
    
    // Здесь размещаем логику работы с HTTPСоединение или WSПрокси
    Попытка
        // Выполнение запроса к веб-сервису...
        // Ответ = ВебСервис.ОтправитьДанные(ДанныеДляОтправки);
        ЗаписьЖурналаРегистрации("Интеграция", УровеньЖурналаРегистрации.Информация, , СсылкаНаДокумент, "Данные успешно отправлены");
    Исключение
        ЗаписьЖурналаРегистрации("Интеграция", УровеньЖурналаРегистрации.Ошибка, , СсылкаНаДокумент, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;

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

Запуск фонового задания из формы документа

Теперь разберем, как инициировать выполнение этого кода. Чтобы не тормозить запись, вызов фонового задания следует делать в обработчике ПослеЗаписиНаСервере в модуле формы (также через расширение формы). Почему именно там? Потому что в этот момент основная транзакция записи уже завершена, документ зафиксирован в базе данных, и ссылка на него гарантированно доступна для фонового задания.

Используем программный интерфейс БСП — модуль ДлительныеОперации. Проанализируем пример вызова:


&НаСервере
Процедура _ПослеЗаписиНаСервереПосле(ТекущийОбъект, ПараметрыЗаписи)
    
    // Подготовим параметры для фонового задания
    ПараметрыПроцедуры = Новый Структура;
    ПараметрыПроцедуры.Вставить("Ссылка", ТекущийОбъект.Ссылка);
    ПараметрыПроцедуры.Вставить("Данные", "Любая необходимая информация");
    
    НаименованиеЗадания = НСтр("ru = 'Отправка данных документа в веб-сервис'");
    
    // Запускаем фоновое задание через БСП
    // Метод выполняет запуск процедуры в фоновом режиме
    ДлительныеОперации.ВыполнитьПроцедуру(
        "__ИнтеграцияВнешнийСервис.ВыполнитьОбменССервисом", 
        ПараметрыПроцедуры, 
        НаименованиеЗадания);
        
КонецПроцедуры

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

Оптимизация: выполнение только при записи из формы

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

В модуле формы, перед тем как вызвать Записать(), мы можем пометить объект специальным флагом. Это позволит процедурам в расширении понять контекст вызова.


&НаКлиенте
Процедура ЗаписатьИВыполнитьОбмен(Команда)
    
    // Добавляем признак интерактивной записи
    ЭтотОбъект.ДополнительныеСвойства.Вставить("ЗапуститьФоновыйОбмен", Истина);
    
    ЭтотОбъект.Записать();
    
КонецПроцедуры

Затем в серверном обработчике расширения проверяем наличие этого свойства:


&НаСервере
Процедура _ПослеЗаписиНаСервереПосле(ТекущийОбъект, ПараметрыЗаписи)
    
    Если ТекущийОбъект.ДополнительныеСвойства.Свойство("ЗапуститьФоновыйОбмен") Тогда
        // Запускаем фоновую операцию, как описано выше
    КонецЕсли;

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

Альтернатива: Использование Очереди заданий БСП

Если веб-сервис, к которому мы обращаемся, часто бывает недоступен, обычное фоновое задание может просто завершиться с ошибкой, и данные не будут переданы. Для более надежной работы рассмотрим механизм Очереди заданий БСП. Это позволит системе автоматически повторять попытки отправки при сбоях.

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

Резюме по шагам реализации

Для достижения цели — выполнения длительной операции без торможения формы и с минимумом изменений — придерживаемся следующего алгоритма:

  1. Используем расширение: Это сохранит типовую конфигурацию в чистоте.
  2. Выносим код в общий модуль: Процедура должна быть экспортной и находиться на сервере.
  3. Применяем асинхронность: Используем ДлительныеОперации.ВыполнитьПроцедуру для запуска кода вне основного потока выполнения.
  4. Соблюдаем границы транзакций: Всегда инициируем фоновые задания только после успешного завершения записи объекта (событие ПослеЗаписи), чтобы избежать передачи в веб-сервис данных, которые еще не зафиксированы в базе.
  5. Контролируем выполнение: Обязательно логируем результаты работы фонового задания в ЖурналРегистрации, так как пользователь не увидит сообщение об ошибке, если оно возникнет в фоне.

Такой подход является эталонным для современной разработки на платформе 1С 8.3 с использованием БСП. Он обеспечивает стабильность системы, предотвращает избыточные блокировки таблиц БД и делает работу пользователя комфортной, избавляя его от необходимости наблюдать "песочные часы" при каждом сохранении документа.

← На главную