Транзакции Бд Между Сервисами

В процессе рефакторинга системы и декомпозиции функционала на отдельные сервисы и службы, возникла интересная проблема.

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

Например, есть сервис, отвечающий за добавление платежей в систему биллинга, есть сервис, отвечающий за добавление услуг пользователю.

Дело в том, что каждый метод этого сервиса может использоваться отдельно и независимо из внешнего приложения.

Но в то же время его могут использовать и другие сервисы.

Например при добавлении пользователю услуги получается так (псевдокод, который сочиняю на ходу):




public function addOption($customer) {

   $tr = $this->beginTransaction(); // каким-то образом начинаем транзацию

   

   try {

       /// Дальше создаем модели, выполняем какие-то манипуляции и вызываем другой сервис, который делает свою часть работы

       $AnotherService = getAnotherService();

       $AnotherService->someOperation();

   catch (Exception $e) {

     $tr->rollback();

   }

   $tr->commit();   

}



Проблема заключается в том, что сервис $AnotherService внутри совего метода тоже ибудет использовать транзакцию и коммитить ее. Таким образом получается "вложенная транзакция", которая коммитится во внутреннем сервисе. А вложенные транзакции не поддерживаются.

Не уверен, что понятно сформулировал, но суть именно такая.

Может быть кто-то сталкивался с подобной проблемой?

Используйте ENestedPdo (гуглить ENestedPDO+yii) оно использует savepoints, работает только для mysql/postgresq; либо проверяй стартовал ли кто-то уже транзакцию, если нет, то CDbConnection#currentTransaction будет null.