Skip to content

Commit e8bb28f

Browse files
committed
Merge branch '6.4' into 7.1
* 6.4: relax assertions on generated hashes [Messenger] ensure exception on rollback does not hide previous exception require the writer to implement getFormats() in the translation:extract don't require fake notifier transports to be installed as non-dev dependencies Remove 5.4 branch from PR template [Scheduler] Fix optional count variable in testGetNextRunDates
2 parents daccae6 + 2ba7e74 commit e8bb28f

File tree

2 files changed

+34
-8
lines changed

2 files changed

+34
-8
lines changed

Messenger/DoctrineTransactionMiddleware.php

+10-2
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,30 @@ class DoctrineTransactionMiddleware extends AbstractDoctrineMiddleware
2727
protected function handleForManager(EntityManagerInterface $entityManager, Envelope $envelope, StackInterface $stack): Envelope
2828
{
2929
$entityManager->getConnection()->beginTransaction();
30+
31+
$success = false;
3032
try {
3133
$envelope = $stack->next()->handle($envelope, $stack);
3234
$entityManager->flush();
3335
$entityManager->getConnection()->commit();
3436

37+
$success = true;
38+
3539
return $envelope;
3640
} catch (\Throwable $exception) {
37-
$entityManager->getConnection()->rollBack();
38-
3941
if ($exception instanceof HandlerFailedException) {
4042
// Remove all HandledStamp from the envelope so the retry will execute all handlers again.
4143
// When a handler fails, the queries of allegedly successful previous handlers just got rolled back.
4244
throw new HandlerFailedException($exception->getEnvelope()->withoutAll(HandledStamp::class), $exception->getWrappedExceptions());
4345
}
4446

4547
throw $exception;
48+
} finally {
49+
$connection = $entityManager->getConnection();
50+
51+
if (!$success && $connection->isTransactionActive()) {
52+
$connection->rollBack();
53+
}
4654
}
4755
}
4856
}

Tests/Messenger/DoctrineTransactionMiddlewareTest.php

+24-6
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,37 @@ public function testMiddlewareWrapsInTransactionAndFlushes()
5656

5757
public function testTransactionIsRolledBackOnException()
5858
{
59-
$this->connection->expects($this->once())
60-
->method('beginTransaction')
61-
;
62-
$this->connection->expects($this->once())
63-
->method('rollBack')
64-
;
59+
$this->connection->expects($this->once())->method('beginTransaction');
60+
$this->connection->expects($this->once())->method('isTransactionActive')->willReturn(true);
61+
$this->connection->expects($this->once())->method('rollBack');
6562

6663
$this->expectException(\RuntimeException::class);
6764
$this->expectExceptionMessage('Thrown from next middleware.');
6865

6966
$this->middleware->handle(new Envelope(new \stdClass()), $this->getThrowingStackMock());
7067
}
7168

69+
public function testExceptionInRollBackDoesNotHidePreviousException()
70+
{
71+
$this->connection->expects($this->once())->method('beginTransaction');
72+
$this->connection->expects($this->once())->method('isTransactionActive')->willReturn(true);
73+
$this->connection->expects($this->once())->method('rollBack')->willThrowException(new \RuntimeException('Thrown from rollBack.'));
74+
75+
try {
76+
$this->middleware->handle(new Envelope(new \stdClass()), $this->getThrowingStackMock());
77+
} catch (\Throwable $exception) {
78+
}
79+
80+
self::assertNotNull($exception);
81+
self::assertInstanceOf(\RuntimeException::class, $exception);
82+
self::assertSame('Thrown from rollBack.', $exception->getMessage());
83+
84+
$previous = $exception->getPrevious();
85+
self::assertNotNull($previous);
86+
self::assertInstanceOf(\RuntimeException::class, $previous);
87+
self::assertSame('Thrown from next middleware.', $previous->getMessage());
88+
}
89+
7290
public function testInvalidEntityManagerThrowsException()
7391
{
7492
$managerRegistry = $this->createMock(ManagerRegistry::class);

0 commit comments

Comments
 (0)