Как запустить процедуру строго после завершения транзакции записи документа в 1С?

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

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

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

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

Разберем ситуацию: когда выполняется код в процедуре ПриЗаписи, транзакция еще активна. Если в этот момент запустить процедуру, которая делает сложную выборку по базе данных (например, остатки с учетом текущего документа), запрос может вернуть неактуальные данные, так как физически изменения в таблицы базы данных еще не подтверждены. Если же транзакция по какой-то причине прервется (произойдет Отказ = Истина), а ваша процедура уже выполнит действия (например, отправит HTTP-запрос во внешнюю систему), возникнет логическая ошибка. Поэтому нам нужно решение, гарантирующее «выход» за пределы транзакции. Для отслеживания порядка вызова обработчиков можно использовать инструмент для изучения событий 1С.

Решение 1: Использование метода ЗапуститьПослеЗавершенияТранзакции (Платформа 8.3.25+)

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

Рассмотрим пример реализации в модуле документа:


Процедура ПриЗаписи(Отказ)
    
    // Регистрируем процедуру, которая выполнится ПОСЛЕ фиксации транзакции
    ОписаниеОповещения = Новый ОписаниеОповещения("ВыполнитьОбработкуПослеЗаписи", ЭтотОбъект);
    ЗапуститьПослеЗавершенияТранзакции(ОписаниеОповещения);
    
КонецПроцедуры

Процедура ВыполнитьОбработкуПослеЗаписи(Параметры) Экспорт
    // Здесь документ уже гарантированно записан, и транзакция завершена.
    // Можно выполнять запросы и обновлять связанные данные.
    ВыполнитьСложныеРасчетыПоДокументу(ЭтотОбъект.Ссылка);
КонецПроцедуры

Важно помнить: если транзакция будет отменена, процедура ВыполнитьОбработкуПослеЗаписи просто не запустится. Это наиболее безопасный и производительный метод.

Решение 2: Фоновое задание с механизмом ожидания блокировки

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

Алгоритм работы:

  1. В процедуре ПриЗаписи мы запускаем фоновое задание и передаем ему ссылку на наш документ.
  2. Фоновое задание начинает работу немедленно в отдельном сеансе.
  3. Первым делом в фоновом задании мы пытаемся установить исключительную блокировку на этот документ.
  4. Пока основная транзакция записи документа не завершена, фоновое задание будет «ждать» на попытке блокировки.
  5. Как только транзакция в основном сеансе завершится (успешно или нет), замок снимется, фоновое задание получит доступ и продолжит выполнение.

Посмотрим на пример кода в модуле документа:


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

И код в общем модуле (с установленным флагом «Сервер»):


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

Решение 3: Очередь заданий БСП (Библиотека стандартных подсистем)

Если вы работаете в современной конфигурации (ERP, КА, УТ 11, БП 3.0), выясним, как использовать штатные механизмы БСП. Использование подсистемы «Очередь заданий» — это более надежный способ, чем ручной запуск фоновых заданий, так как БСП берет на себя управление очередностью и повторные попытки при сбоях.

Выясним причину, почему это удобно: вы просто записываете намерение выполнить действие в специальный регистр сведений (Очередь заданий) в той же транзакции. Если запись документа пройдет успешно — запись в очереди тоже сохранится. Если будет откат — запись в очереди исчезнет. Регламентное задание подхватит вашу задачу через несколько секунд после фиксации. Для полноценного использования этого механизма доступен раздел с решениями для перехода на 1С:ERP и другие современные системы.

Пример использования метода БСП ОчередьЗаданий.ДобавитьЗадание:


// В модуле документа
Процедура ПриЗаписи(Отказ)
    Если ОбменДанными.Загрузка Тогда Возврат; КонецЕсли;
    
    ПараметрыМетода = Новый Массив;
    ПараметрыМетода.Добавить(ЭтотОбъект.Ссылка);
    
    Задание = Новый Структура;
    Задание.Вставить("ИмяМетода", "ОбщийМодульСервер.МояПроцедураОбработки");
    Задание.Вставить("Параметры", ПараметрыМетода);
    
    // БСП сама определит, когда выполнить это задание после фиксации транзакции
    ОчередьЗаданий.ДобавитьЗадание(Задание);
КонецПроцедуры

Решение 4: Вызов HTTP-сервиса «самого себя»

Проанализируем ситуацию в высоконагруженных системах, где важно максимально быстро освободить рабочий процесс. Метод заключается в отправке асинхронного HTTP-запроса к опубликованному HTTP-сервису этой же базы данных.

Почему это работает? HTTP-запрос инициирует новое соединение с базой данных. Поскольку сетевой пакет дойдет до веб-сервера и вернется в 1С через микросекунды после отправки, а отправка происходит в самом конце процедуры ПриЗаписи, вероятность того, что транзакция уже завершится, крайне высока. Но для надежности в HTTP-сервисе все равно стоит использовать проверку существования данных или краткую паузу/повтор (Retry).

Рекомендации по выбору метода

Рассмотрим критерии, по которым стоит выбирать решение:

  1. Версия платформы: Если у вас 8.3.25 и выше — всегда используйте ЗапуститьПослеЗавершенияТранзакции. Это нативно, быстро и не создает лишних сеансов.
  2. Интерактивность: Если код должен сработать только при работе пользователя в форме, можно использовать событие формы ПослеЗаписи. Но помните, что при записи программно (обработкой) этот код не выполнится.
  3. Надежность: Если критически важно, чтобы расчет выполнился в любом случае, даже если сервер упадет через секунду после записи документа — используйте Очередь заданий БСП.
  4. Скорость отклика: Если нужно «мгновенно» (в течение доли секунды) — лучше всего подходит фоновое задание.

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

Таким образом, мы рассмотрели все основные способы выполнения кода после фиксации документа. Правильный выбор инструмента позволит вам строить надежные и быстрые системы на базе «1С:Предприятие». В таких системах важно выявлять расхождения данных путём автоматической сверки проводок между информационными базами.

← На главную