[Messenger] Fix exception message of failed message is dropped on retry
This commit is contained in:
parent
ad6dc2ec06
commit
8f9f44eb21
@ -13,12 +13,15 @@ namespace Symfony\Component\Messenger\Tests\Command;
|
||||
|
||||
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 @@ class FailedMessagesRetryCommandTest extends TestCase
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
@ -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 @@ class Worker implements WorkerInterface
|
||||
|
||||
// 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 @@ class Worker implements WorkerInterface
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user