From 8f9f44eb21d5cd29ce41277080b9e986a9da822a Mon Sep 17 00:00:00 2001 From: "tien.xuan.vo" Date: Mon, 16 Sep 2019 23:41:10 +0700 Subject: [PATCH] [Messenger] Fix exception message of failed message is dropped on retry --- .../FailedMessagesRetryCommandTest.php | 53 ++++++++++++++++--- src/Symfony/Component/Messenger/Worker.php | 16 +++++- 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRetryCommandTest.php b/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRetryCommandTest.php index bcc67f79d566b..bc69a1c2e8a2e 100644 --- a/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRetryCommandTest.php +++ b/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRetryCommandTest.php @@ -13,12 +13,15 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\Debug\Exception\FlattenException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Messenger\Command\FailedMessagesRetryCommand; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\MessageBusInterface; +use Symfony\Component\Messenger\Retry\RetryStrategyInterface; +use Symfony\Component\Messenger\Stamp\ReceivedStamp; +use Symfony\Component\Messenger\Stamp\RedeliveryStamp; use Symfony\Component\Messenger\Transport\Receiver\ListableReceiverInterface; -use Symfony\Component\Messenger\Worker; class FailedMessagesRetryCommandTest extends TestCase { @@ -34,16 +37,52 @@ public function testBasicRun() // the bus should be called in the worker $bus->expects($this->exactly(2))->method('dispatch')->willReturn(new Envelope(new \stdClass())); - $command = new FailedMessagesRetryCommand( - 'failure_receiver', - $receiver, - $bus, - $dispatcher - ); + $command = new FailedMessagesRetryCommand('failure_receiver', $receiver, $bus, $dispatcher); $tester = new CommandTester($command); $tester->execute(['id' => [10, 12]]); $this->assertStringContainsString('[OK]', $tester->getDisplay()); } + + public function testExceptionOnRetry() + { + $receiver = $this->createMock(ListableReceiverInterface::class); + $receiver->expects($this->once())->method('find')->with(10)->willReturn(new Envelope(new \stdClass())); + // message will eventually be ack'ed in Worker + $receiver->expects($this->once())->method('ack'); + + $dispatcher = $this->createMock(EventDispatcherInterface::class); + $bus = $this->createMock(MessageBusInterface::class); + // the bus should be called in the worker + $bus->expects($this->at(0)) + ->method('dispatch') + ->with($this->callback(function (Envelope $envelope) { + $lastReceivedStamp = $envelope->last(ReceivedStamp::class); + + return $lastReceivedStamp instanceof ReceivedStamp && \is_string($lastReceivedStamp->getTransportName()); + })) + ->will($this->throwException(new \Exception('Mock test exception'))); + + $bus->expects($this->at(1)) + ->method('dispatch') + ->with($this->callback(function (Envelope $envelope) { + $lastRedeliveryStamp = $envelope->last(RedeliveryStamp::class); + + return $lastRedeliveryStamp instanceof RedeliveryStamp && + \is_string($lastRedeliveryStamp->getExceptionMessage()) && + $lastRedeliveryStamp->getFlattenException() instanceof FlattenException; + })) + ->willReturn(new Envelope(new \stdClass())); + + $retryStrategy = $this->createMock(RetryStrategyInterface::class); + $retryStrategy->expects($this->once())->method('isRetryable')->with($this->isInstanceOf(Envelope::class))->willReturn(true); + + $command = new FailedMessagesRetryCommand('failure_receiver', $receiver, $bus, $dispatcher, $retryStrategy); + + $tester = new CommandTester($command); + $tester->execute(['id' => [10]]); + + $this->assertStringContainsString('[OK]', $tester->getDisplay()); + } } diff --git a/src/Symfony/Component/Messenger/Worker.php b/src/Symfony/Component/Messenger/Worker.php index 6bfb4cb675220..f463dde78422f 100644 --- a/src/Symfony/Component/Messenger/Worker.php +++ b/src/Symfony/Component/Messenger/Worker.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Messenger; use Psr\Log\LoggerInterface; +use Symfony\Component\Debug\Exception\FlattenException; use Symfony\Component\Messenger\Event\WorkerMessageFailedEvent; use Symfony\Component\Messenger\Event\WorkerMessageHandledEvent; use Symfony\Component\Messenger\Event\WorkerMessageReceivedEvent; @@ -152,7 +153,7 @@ private function handleMessage(Envelope $envelope, ReceiverInterface $receiver, // add the delay and retry stamp info + remove ReceivedStamp $retryEnvelope = $envelope->with(new DelayStamp($delay)) - ->with(new RedeliveryStamp($retryCount, $transportName)) + ->with(new RedeliveryStamp($retryCount, $transportName, $throwable->getMessage(), $this->flattenedException($throwable))) ->withoutAll(ReceivedStamp::class); // re-send the message @@ -215,4 +216,17 @@ private function shouldRetry(\Throwable $e, Envelope $envelope, RetryStrategyInt return $retryStrategy->isRetryable($envelope); } + + private function flattenedException(\Throwable $throwable): ?FlattenException + { + if (!class_exists(FlattenException::class)) { + return null; + } + + if ($throwable instanceof HandlerFailedException) { + $throwable = $throwable->getNestedExceptions()[0]; + } + + return FlattenException::createFromThrowable($throwable); + } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy