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