Код-ревью Middle Транзакции и блокировки обновлено
Ревью кода с транзакцией
Вопрос
Обработка переносит остатки между складами. Найдите ошибки работы с транзакцией и блокировками.
Попытка
НачатьТранзакцию();
Для Каждого Строка Из Товары Цикл
Остаток = ПолучитьОстаток(Строка.Номенклатура, СкладИз);
Если Остаток < Строка.Количество Тогда
Ответ = Вопрос("Не хватает. Продолжить?", РежимДиалогаВопрос.ДаНет);
КонецЕсли;
ЗаписатьПеремещение(Строка);
КонецЦикла;
ОтправитьВоВнешнююСистему(Товары);
ЗафиксироватьТранзакцию();
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
Коротко
Правильный шаблон: НачатьТранзакцию, Попытка, блокировка, чтение одним запросом, запись, ЗафиксироватьТранзакцию, Исключение: ОтменитьТранзакцию и ВызватьИсключение. Без интерактива и внешних вызовов внутри.
Что должен найти ревьюер
- Ошибкастрока 2НачатьТранзакцию() должен стоять перед Попытка: иначе при исключении в самом начале обработчик попытается работать с несуществующей транзакцией.
- Ошибкастрока 4Остаток читается без управляемой блокировки: параллельная операция успеет списать тот же товар.
- Производительностьстрока 4Запрос остатка в цикле по строкам: нужно получить остатки всех товаров одним запросом.
- Ошибкастрока 6Модальный вопрос пользователю внутри транзакции: блокировки держатся, пока человек думает, и это клиентский метод в серверном коде.
- Производительностьстрока 10Внешний вызов внутри транзакции растягивает её и не откатывается. Выносить после фиксации или в очередь.
- Ошибкастрока 13В Исключение нет ОтменитьТранзакцию() и ВызватьИсключение: транзакция остаётся открытой, а ошибка проглатывается.
Разбор
Правильный шаблон: НачатьТранзакцию, Попытка, блокировка, чтение одним запросом, запись, ЗафиксироватьТранзакцию, Исключение: ОтменитьТранзакцию и ВызватьИсключение. Без интерактива и внешних вызовов внутри.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.