diff --git a/Exception/DelayedMessageHandlingException.php b/Exception/DelayedMessageHandlingException.php index 77307800..f3500242 100644 --- a/Exception/DelayedMessageHandlingException.php +++ b/Exception/DelayedMessageHandlingException.php @@ -23,9 +23,10 @@ class DelayedMessageHandlingException extends RuntimeException implements Wrappe { use WrappedExceptionsTrait; - private Envelope $envelope; + private array $exceptions; + private ?Envelope $envelope; - public function __construct(array $exceptions, Envelope $envelope) + public function __construct(array $exceptions, Envelope $envelope = null) { $this->envelope = $envelope; @@ -45,7 +46,7 @@ public function __construct(array $exceptions, Envelope $envelope) parent::__construct($message, 0, $exceptions[array_key_first($exceptions)]); } - public function getEnvelope(): Envelope + public function getEnvelope(): ?Envelope { return $this->envelope; } diff --git a/Exception/HandlerFailedException.php b/Exception/HandlerFailedException.php index 29991d95..c3390ae6 100644 --- a/Exception/HandlerFailedException.php +++ b/Exception/HandlerFailedException.php @@ -20,7 +20,7 @@ class HandlerFailedException extends RuntimeException implements WrappedExceptio private Envelope $envelope; /** - * @param \Throwable[] $exceptions + * @param \Throwable[] $exceptions The name of the handler should be given as key */ public function __construct(Envelope $envelope, array $exceptions) { diff --git a/Middleware/HandleMessageMiddleware.php b/Middleware/HandleMessageMiddleware.php index a8014a3e..c4e4a2d0 100644 --- a/Middleware/HandleMessageMiddleware.php +++ b/Middleware/HandleMessageMiddleware.php @@ -66,7 +66,7 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope if ($batchHandler && $ackStamp = $envelope->last(AckStamp::class)) { $ack = new Acknowledger(get_debug_type($batchHandler), static function (\Throwable $e = null, $result = null) use ($envelope, $ackStamp, $handlerDescriptor) { if (null !== $e) { - $e = new HandlerFailedException($envelope, [$e]); + $e = new HandlerFailedException($envelope, [$handlerDescriptor->getName() => $e]); } else { $envelope = $envelope->with(HandledStamp::fromDescriptor($handlerDescriptor, $result)); } @@ -95,7 +95,7 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope $envelope = $envelope->with($handledStamp); $this->logger?->info('Message {class} handled by {handler}', $context + ['handler' => $handledStamp->getHandlerName()]); } catch (\Throwable $e) { - $exceptions[] = $e; + $exceptions[$handlerDescriptor->getName()] = $e; } } @@ -107,7 +107,7 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope $handler = $stamp->getHandlerDescriptor()->getBatchHandler(); $handler->flush($flushStamp->force()); } catch (\Throwable $e) { - $exceptions[] = $e; + $exceptions[$stamp->getHandlerDescriptor()->getName()] = $e; } } } diff --git a/Tests/Middleware/HandleMessageMiddlewareTest.php b/Tests/Middleware/HandleMessageMiddlewareTest.php index d05cf736..13b0bb85 100644 --- a/Tests/Middleware/HandleMessageMiddlewareTest.php +++ b/Tests/Middleware/HandleMessageMiddlewareTest.php @@ -47,6 +47,36 @@ public function testItCallsTheHandlerAndNextMiddleware() $middleware->handle($envelope, $this->getStackMock()); } + public function testItKeysTheHandlerFailedNestedExceptionsByHandlerDescription() + { + $message = new DummyMessage('Hey'); + $envelope = new Envelope($message); + $handler = new class() { + public function __invoke() + { + throw new \Exception('failed'); + } + }; + + $middleware = new HandleMessageMiddleware(new HandlersLocator([ + DummyMessage::class => [$handler], + ])); + + try { + $middleware->handle($envelope, $this->getStackMock(false)); + } catch (HandlerFailedException $e) { + $key = (new HandlerDescriptor($handler))->getName(); + + $this->assertCount(1, $e->getWrappedExceptions()); + $this->assertArrayHasKey($key, $e->getWrappedExceptions()); + $this->assertSame('failed', $e->getWrappedExceptions()[$key]->getMessage()); + + return; + } + + $this->fail('Exception not thrown.'); + } + /** * @dataProvider itAddsHandledStampsProvider */ diff --git a/Tests/Stamp/StringErrorCodeException.php b/Tests/Stamp/StringErrorCodeException.php deleted file mode 100644 index 63d6f88e..00000000 --- a/Tests/Stamp/StringErrorCodeException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Messenger\Tests\Stamp; - -class StringErrorCodeException extends \Exception -{ - public function __construct(string $message, string $code) - { - parent::__construct($message); - $this->code = $code; - } -} diff --git a/Worker.php b/Worker.php index 3dc85b52..eb0af634 100644 --- a/Worker.php +++ b/Worker.php @@ -189,7 +189,7 @@ private function ack(): bool $receiver->reject($envelope); } - if ($e instanceof HandlerFailedException || $e instanceof DelayedMessageHandlingException) { + if ($e instanceof HandlerFailedException || ($e instanceof DelayedMessageHandlingException && null !== $e->getEnvelope())) { $envelope = $e->getEnvelope(); }