переопределить Yii-ные beginTransaction и commit, чтобы они работали так:
при повторном (вложенном) вызове beginTransaction транзакция не стартует, вместо нее возвращается TransactionNullObject
при повторном (вложенном) вызове commit транзакция не будет комититься, вместо нее будет вызываться фиктивный commit -метод объекта TransactionNullObject
TransactionNullObject это реализация паттерна https://designpatternsphp.readthedocs.io/ru/latest/Behavioral/NullObject/README.html
Пример проблемы:
db->beginTransaction();
try {
// first SQL of first transaction
$transaction2 = Yii::app()->db->beginTransaction();
try {
// some SQL of second transaction
$transaction2->commit();// тут закомитится "first SQL of first transaction" + "some SQL of second transaction"
} catch (\Exception $exception) {
$transaction2->rollback();
}
// second SQL of first transaction (если выше будет вызван $transaction2->rollback(); то этот SQL отработает и ниже мы его закомитим)
$transaction->commit();// т.к. $transaction2->commit(); уже закомитил транзакцию, то тут будет ошибка - транзакция не начата
} catch (\Exception $exception) {
$transaction->rollback();
}
В нашем репозитории полно подобных ситуаций и вот например одна из них:
в классе \Gs\Office\Service\PatientDeduplication\PatientDeduplicationService есть функция updatePatientRelations (транзакция) -> updateMainPatient (вложенная транзакция) -> updateMainPatientForPatients (вложенная транзакция - третий уровень)
Решение видится в создании своего объекта NullTransaction это реализация паттерна https://designpatternsphp.readthedocs.io/ru/latest/Behavioral/NullObject/README.html
Итого, что предется переопределить:
\CDbConnection
\CDbTransaction
Подмену Yii классов можно реализовать с помощью composer-a.
Обязательным будет покрытие тестами такого функционала.
Комментарии
Комментариев пока нет.