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