From 11d3840df7f67d553a98d98fc91a2d5d7cfd51e3 Mon Sep 17 00:00:00 2001 From: Milen Dzhambazov Date: Thu, 29 May 2025 14:00:44 +0300 Subject: [PATCH 1/2] https://github.com/doctrine/migrations/issues/1458 --- .../CatastrophicMigrationException.php | 11 +++++ .../TransactionRollbackException.php | 25 +++++++++++ src/Version/DbalExecutor.php | 45 ++++++++++++++----- 3 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 src/Exception/CatastrophicMigrationException.php create mode 100644 src/Exception/TransactionRollbackException.php diff --git a/src/Exception/CatastrophicMigrationException.php b/src/Exception/CatastrophicMigrationException.php new file mode 100644 index 000000000..a2985173b --- /dev/null +++ b/src/Exception/CatastrophicMigrationException.php @@ -0,0 +1,11 @@ +rollbackCausationalException; + } + + public function setRollbackCausationalException(\Throwable $rollbackCausationalException): static + { + $this->rollbackCausationalException = $rollbackCausationalException; + + return $this; + } +} diff --git a/src/Version/DbalExecutor.php b/src/Version/DbalExecutor.php index 57712e479..35ba1aa0e 100644 --- a/src/Version/DbalExecutor.php +++ b/src/Version/DbalExecutor.php @@ -10,6 +10,7 @@ use Doctrine\Migrations\AbstractMigration; use Doctrine\Migrations\EventDispatcher; use Doctrine\Migrations\Events; +use Doctrine\Migrations\Exception\TransactionRollbackException; use Doctrine\Migrations\Exception\SkipMigration; use Doctrine\Migrations\Metadata\MigrationPlan; use Doctrine\Migrations\Metadata\Storage\MetadataStorage; @@ -228,8 +229,19 @@ private function migrationEnd(Throwable $e, MigrationPlan $plan, ExecutionResult { $migration = $plan->getMigration(); if ($migration->isTransactional()) { - //only rollback transaction if in transactional mode - TransactionHelper::rollbackIfInTransaction($this->connection); + try { + //only rollback transaction if in transactional mode + TransactionHelper::rollbackIfInTransaction($this->connection); + } catch (\Exception $transactionRollbackException) { + $this->logResult( + (new TransactionRollbackException( + 'The migration transaction could not be rolled back after an encountered exception during its execution.', + previous: $transactionRollbackException + ))->setRollbackCausationalException($e), + $result, + $plan + ); + } } $plan->markAsExecuted($result); @@ -254,14 +266,27 @@ private function logResult(Throwable $e, ExecutionResult $result, MigrationPlan ], ); } elseif ($result->hasError()) { - $this->logger->error( - 'Migration {version} failed during {state}. Error: "{error}"', - [ - 'version' => (string) $plan->getVersion(), - 'error' => $e->getMessage(), - 'state' => $this->getExecutionStateAsString($result->getState()), - ], - ); + if ($e instanceof TransactionRollbackException) { + $this->logger->error( + 'Migration {version} failed catastrophically at {state} during the error handling routine.' + . ' Error: "{error}". Original error: {originalError}', + [ + 'version' => (string)$plan->getVersion(), + 'error' => $e->getMessage(), + 'originalError' => $e->getRollbackCausationalException()->getMessage(), + 'state' => $this->getExecutionStateAsString($result->getState()), + ], + ); + } else { + $this->logger->error( + 'Migration {version} failed during {state}. Error: "{error}"', + [ + 'version' => (string)$plan->getVersion(), + 'error' => $e->getMessage(), + 'state' => $this->getExecutionStateAsString($result->getState()), + ], + ); + } } } From b48690fa7d1ff7fdcb12a279c5778cf57f567db0 Mon Sep 17 00:00:00 2001 From: Milen Dzhambazov Date: Thu, 29 May 2025 15:30:15 +0300 Subject: [PATCH 2/2] https://github.com/doctrine/migrations/issues/1458 #2 --- .../CatastrophicMigrationException.php | 5 +++- .../CatastrophicMigrationExceptionTrait.php | 24 +++++++++++++++++++ .../TransactionRollbackException.php | 15 +----------- src/Version/DbalExecutor.php | 9 +++---- 4 files changed, 34 insertions(+), 19 deletions(-) create mode 100644 src/Exception/CatastrophicMigrationExceptionTrait.php diff --git a/src/Exception/CatastrophicMigrationException.php b/src/Exception/CatastrophicMigrationException.php index a2985173b..bf28a308d 100644 --- a/src/Exception/CatastrophicMigrationException.php +++ b/src/Exception/CatastrophicMigrationException.php @@ -6,6 +6,9 @@ use Throwable; -interface CatastrophicMigrationException extends Throwable +interface CatastrophicMigrationException { + + public function getAdditionalException(): Throwable; + public function setAdditionalException(Throwable $additionalException): static; } diff --git a/src/Exception/CatastrophicMigrationExceptionTrait.php b/src/Exception/CatastrophicMigrationExceptionTrait.php new file mode 100644 index 000000000..c97ce8609 --- /dev/null +++ b/src/Exception/CatastrophicMigrationExceptionTrait.php @@ -0,0 +1,24 @@ +additionalException; + } + + public function setAdditionalException(Throwable $additionalException): static + { + $this->additionalException = $additionalException; + + return $this; + } +} diff --git a/src/Exception/TransactionRollbackException.php b/src/Exception/TransactionRollbackException.php index b75ac35b0..377799363 100644 --- a/src/Exception/TransactionRollbackException.php +++ b/src/Exception/TransactionRollbackException.php @@ -5,21 +5,8 @@ namespace Doctrine\Migrations\Exception; use RuntimeException; -use Throwable; class TransactionRollbackException extends RuntimeException implements CatastrophicMigrationException { - protected Throwable $rollbackCausationalException; - - public function getRollbackCausationalException(): Throwable - { - return $this->rollbackCausationalException; - } - - public function setRollbackCausationalException(\Throwable $rollbackCausationalException): static - { - $this->rollbackCausationalException = $rollbackCausationalException; - - return $this; - } + use CatastrophicMigrationExceptionTrait; } diff --git a/src/Version/DbalExecutor.php b/src/Version/DbalExecutor.php index 35ba1aa0e..db098a039 100644 --- a/src/Version/DbalExecutor.php +++ b/src/Version/DbalExecutor.php @@ -10,6 +10,7 @@ use Doctrine\Migrations\AbstractMigration; use Doctrine\Migrations\EventDispatcher; use Doctrine\Migrations\Events; +use Doctrine\Migrations\Exception\CatastrophicMigrationException; use Doctrine\Migrations\Exception\TransactionRollbackException; use Doctrine\Migrations\Exception\SkipMigration; use Doctrine\Migrations\Metadata\MigrationPlan; @@ -237,7 +238,7 @@ private function migrationEnd(Throwable $e, MigrationPlan $plan, ExecutionResult (new TransactionRollbackException( 'The migration transaction could not be rolled back after an encountered exception during its execution.', previous: $transactionRollbackException - ))->setRollbackCausationalException($e), + ))->setAdditionalException($e), $result, $plan ); @@ -266,14 +267,14 @@ private function logResult(Throwable $e, ExecutionResult $result, MigrationPlan ], ); } elseif ($result->hasError()) { - if ($e instanceof TransactionRollbackException) { + if ($e instanceof CatastrophicMigrationException) { $this->logger->error( 'Migration {version} failed catastrophically at {state} during the error handling routine.' - . ' Error: "{error}". Original error: {originalError}', + . ' Error: "{error}". Additional error: {additionalError}', [ 'version' => (string)$plan->getVersion(), 'error' => $e->getMessage(), - 'originalError' => $e->getRollbackCausationalException()->getMessage(), + 'additionalError' => $e->getAdditionalException()->getMessage(), 'state' => $this->getExecutionStateAsString($result->getState()), ], );