api/symfony/Component/Messenger/Tests/FailureIntegrationTest.yaml

333 lines
22 KiB
YAML
Raw Normal View History

2024-09-26 09:03:21 +00:00
name: FailureIntegrationTest
class_comment: null
dependencies:
- name: TestCase
type: class
source: PHPUnit\Framework\TestCase
- name: NullLogger
type: class
source: Psr\Log\NullLogger
- name: Container
type: class
source: Symfony\Component\DependencyInjection\Container
- name: ServiceLocator
type: class
source: Symfony\Component\DependencyInjection\ServiceLocator
- name: EventDispatcher
type: class
source: Symfony\Component\EventDispatcher\EventDispatcher
- name: Envelope
type: class
source: Symfony\Component\Messenger\Envelope
- name: WorkerMessageFailedEvent
type: class
source: Symfony\Component\Messenger\Event\WorkerMessageFailedEvent
- name: AddErrorDetailsStampListener
type: class
source: Symfony\Component\Messenger\EventListener\AddErrorDetailsStampListener
- name: SendFailedMessageForRetryListener
type: class
source: Symfony\Component\Messenger\EventListener\SendFailedMessageForRetryListener
- name: SendFailedMessageToFailureTransportListener
type: class
source: Symfony\Component\Messenger\EventListener\SendFailedMessageToFailureTransportListener
- name: StopWorkerOnMessageLimitListener
type: class
source: Symfony\Component\Messenger\EventListener\StopWorkerOnMessageLimitListener
- name: DelayedMessageHandlingException
type: class
source: Symfony\Component\Messenger\Exception\DelayedMessageHandlingException
- name: HandlerFailedException
type: class
source: Symfony\Component\Messenger\Exception\HandlerFailedException
- name: ValidationFailedException
type: class
source: Symfony\Component\Messenger\Exception\ValidationFailedException
- name: HandlerDescriptor
type: class
source: Symfony\Component\Messenger\Handler\HandlerDescriptor
- name: HandlersLocator
type: class
source: Symfony\Component\Messenger\Handler\HandlersLocator
- name: MessageBus
type: class
source: Symfony\Component\Messenger\MessageBus
- name: AddBusNameStampMiddleware
type: class
source: Symfony\Component\Messenger\Middleware\AddBusNameStampMiddleware
- name: DispatchAfterCurrentBusMiddleware
type: class
source: Symfony\Component\Messenger\Middleware\DispatchAfterCurrentBusMiddleware
- name: FailedMessageProcessingMiddleware
type: class
source: Symfony\Component\Messenger\Middleware\FailedMessageProcessingMiddleware
- name: HandleMessageMiddleware
type: class
source: Symfony\Component\Messenger\Middleware\HandleMessageMiddleware
- name: SendMessageMiddleware
type: class
source: Symfony\Component\Messenger\Middleware\SendMessageMiddleware
- name: ValidationMiddleware
type: class
source: Symfony\Component\Messenger\Middleware\ValidationMiddleware
- name: MultiplierRetryStrategy
type: class
source: Symfony\Component\Messenger\Retry\MultiplierRetryStrategy
- name: BusNameStamp
type: class
source: Symfony\Component\Messenger\Stamp\BusNameStamp
- name: DispatchAfterCurrentBusStamp
type: class
source: Symfony\Component\Messenger\Stamp\DispatchAfterCurrentBusStamp
- name: ErrorDetailsStamp
type: class
source: Symfony\Component\Messenger\Stamp\ErrorDetailsStamp
- name: SentToFailureTransportStamp
type: class
source: Symfony\Component\Messenger\Stamp\SentToFailureTransportStamp
- name: DummyMessage
type: class
source: Symfony\Component\Messenger\Tests\Fixtures\DummyMessage
- name: ReceiverInterface
type: class
source: Symfony\Component\Messenger\Transport\Receiver\ReceiverInterface
- name: SenderInterface
type: class
source: Symfony\Component\Messenger\Transport\Sender\SenderInterface
- name: SendersLocator
type: class
source: Symfony\Component\Messenger\Transport\Sender\SendersLocator
- name: Worker
type: class
source: Symfony\Component\Messenger\Worker
- name: ConstraintViolation
type: class
source: Symfony\Component\Validator\ConstraintViolation
- name: ConstraintViolationList
type: class
source: Symfony\Component\Validator\ConstraintViolationList
- name: ValidatorInterface
type: class
source: Symfony\Component\Validator\Validator\ValidatorInterface
properties: []
methods:
- name: testRequeueMechanism
visibility: public
parameters: []
comment: null
- name: getMessagesWaitingToBeReceived
visibility: public
parameters: []
comment: "# @var Envelope $failedEnvelope */\n# $failedEnvelope = $failureTransport->getMessagesWaitingToBeReceived()[0];\n\
# /** @var SentToFailureTransportStamp $sentToFailureStamp */\n# $sentToFailureStamp\
\ = $failedEnvelope->last(SentToFailureTransportStamp::class);\n# $this->assertNotNull($sentToFailureStamp);\n\
# /** @var ErrorDetailsStamp $errorDetailsStamp */\n# $errorDetailsStamp = $failedEnvelope->last(ErrorDetailsStamp::class);\n\
# $this->assertNotNull($errorDetailsStamp);\n# $this->assertSame('Failure from\
\ call 2', $errorDetailsStamp->getExceptionMessage());\n# \n# /*\n# * Failed message\
\ is handled, fails, and sent for a retry\n# */\n# $throwable = $runWorker('the_failure_transport');\n\
# // make sure this is failing for the reason we think\n# $this->assertInstanceOf(HandlerFailedException::class,\
\ $throwable);\n# // only the \"failed\" handler is called a 3rd time\n# $this->assertSame(3,\
\ $transport1HandlerThatFails->getTimesCalled());\n# $this->assertSame(1, $allTransportHandlerThatWorks->getTimesCalled());\n\
# // handling fails again, message is retried\n# $this->assertCount(1, $failureTransport->getMessagesWaitingToBeReceived());\n\
# // transport2 still only holds the original message\n# // a new message was\
\ never mistakenly delivered to it\n# $this->assertCount(1, $transport2->getMessagesWaitingToBeReceived());\n\
# \n# /*\n# * Message is retried on failure transport then discarded\n# */\n#\
\ $runWorker('the_failure_transport');\n# // only the \"failed\" handler is called\
\ a 4th time\n# $this->assertSame(4, $transport1HandlerThatFails->getTimesCalled());\n\
# $this->assertSame(1, $allTransportHandlerThatWorks->getTimesCalled());\n# //\
\ handling fails again, message is discarded\n# $this->assertCount(0, $failureTransport->getMessagesWaitingToBeReceived());\n\
# \n# /*\n# * Execute handlers on transport2\n# */\n# $runWorker('transport2');\n\
# // transport1 handler is not called again\n# $this->assertSame(4, $transport1HandlerThatFails->getTimesCalled());\n\
# // all transport handler is now called again\n# $this->assertSame(2, $allTransportHandlerThatWorks->getTimesCalled());\n\
# // transport1 handler called for the first time\n# $this->assertSame(1, $transport2HandlerThatWorks->getTimesCalled());\n\
# // all transport should be empty\n# $this->assertEmpty($transport1->getMessagesWaitingToBeReceived());\n\
# $this->assertEmpty($transport2->getMessagesWaitingToBeReceived());\n# $this->assertEmpty($failureTransport->getMessagesWaitingToBeReceived());\n\
# \n# /*\n# * Dispatch the original message again\n# */\n# $bus->dispatch($envelope);\n\
# // handle the failing message so it goes into the failure transport\n# $runWorker('transport1');\n\
# $runWorker('transport1');\n# // now make the handler work!\n# $transport1HandlerThatFails->setShouldThrow(false);\n\
# $runWorker('the_failure_transport');\n# // the failure transport is empty because\
\ it worked\n# $this->assertEmpty($failureTransport->getMessagesWaitingToBeReceived());\n\
# }\n# \n# public function testMultipleFailedTransportsWithoutGlobalFailureTransport()\n\
# {\n# $transport1 = new DummyFailureTestSenderAndReceiver();\n# $transport2 =\
\ new DummyFailureTestSenderAndReceiver();\n# $failureTransport1 = new DummyFailureTestSenderAndReceiver();\n\
# $failureTransport2 = new DummyFailureTestSenderAndReceiver();\n# \n# $sendersLocatorFailureTransport\
\ = new ServiceLocator([\n# 'transport1' => fn () => $failureTransport1,\n# 'transport2'\
\ => fn () => $failureTransport2,\n# ]);\n# \n# $transports = [\n# 'transport1'\
\ => $transport1,\n# 'transport2' => $transport2,\n# 'the_failure_transport1'\
\ => $failureTransport1,\n# 'the_failure_transport2' => $failureTransport2,\n\
# ];\n# \n# $locator = new Container();\n# \n# foreach ($transports as $transportName\
\ => $transport) {\n# $locator->set($transportName, $transport);\n# }\n# \n# $senderLocator\
\ = new SendersLocator(\n# [DummyMessage::class => ['transport1', 'transport2']],\n\
# $locator\n# );\n# \n# // using to so we can lazily get the bus later and avoid\
\ circular problem\n# $transport1HandlerThatFails = new DummyTestHandler(true);\n\
# $transport2HandlerThatFails = new DummyTestHandler(true);\n# $handlerLocator\
\ = new HandlersLocator([\n# DummyMessage::class => [\n# new HandlerDescriptor($transport1HandlerThatFails,\
\ [\n# 'from_transport' => 'transport1',\n# ]),\n# new HandlerDescriptor($transport2HandlerThatFails,\
\ [\n# 'from_transport' => 'transport2',\n# ]),\n# ],\n# ]);\n# \n# $dispatcher\
\ = new EventDispatcher();\n# $bus = new MessageBus([\n# new FailedMessageProcessingMiddleware(),\n\
# new SendMessageMiddleware($senderLocator),\n# new HandleMessageMiddleware($handlerLocator),\n\
# ]);\n# \n# $dispatcher->addSubscriber(new SendFailedMessageForRetryListener($locator,\
\ new Container()));\n# $dispatcher->addSubscriber(new SendFailedMessageToFailureTransportListener(\n\
# $sendersLocatorFailureTransport,\n# new NullLogger()\n# ));\n# $dispatcher->addSubscriber(new\
\ StopWorkerOnMessageLimitListener(1));\n# \n# $runWorker = function (string $transportName)\
\ use ($transports, $bus, $dispatcher): ?\\Throwable {\n# $throwable = null;\n\
# $failedListener = function (WorkerMessageFailedEvent $event) use (&$throwable)\
\ {\n# $throwable = $event->getThrowable();\n# };\n# $dispatcher->addListener(WorkerMessageFailedEvent::class,\
\ $failedListener);\n# \n# $worker = new Worker([$transportName => $transports[$transportName]],\
\ $bus, $dispatcher);\n# \n# $worker->run();\n# \n# $dispatcher->removeListener(WorkerMessageFailedEvent::class,\
\ $failedListener);\n# \n# return $throwable;\n# };\n# \n# // send the message\n\
# $envelope = new Envelope(new DummyMessage('API'));\n# $bus->dispatch($envelope);\n\
# \n# // message has been sent\n# $this->assertCount(1, $transport1->getMessagesWaitingToBeReceived());\n\
# $this->assertCount(1, $transport2->getMessagesWaitingToBeReceived());\n# $this->assertCount(0,\
\ $failureTransport1->getMessagesWaitingToBeReceived());\n# $this->assertCount(0,\
\ $failureTransport2->getMessagesWaitingToBeReceived());\n# \n# // Receive the\
\ message from \"transport1\"\n# $throwable = $runWorker('transport1');\n# $this->assertInstanceOf(HandlerFailedException::class,\
\ $throwable);\n# // handler for transport1 is called\n# $this->assertSame(1,\
\ $transport1HandlerThatFails->getTimesCalled());\n# $this->assertSame(0, $transport2HandlerThatFails->getTimesCalled());\n\
# // one handler failed and the message is sent to the failed transport of transport1\n\
# $this->assertCount(1, $failureTransport1->getMessagesWaitingToBeReceived());\n\
# $this->assertCount(0, $failureTransport2->getMessagesWaitingToBeReceived());\n\
# \n# // consume the failure message failed on \"transport1\"\n# $runWorker('the_failure_transport1');\n\
# // \"transport1\" handler is called again from the \"the_failed_transport1\"\
\ and it fails\n# $this->assertSame(2, $transport1HandlerThatFails->getTimesCalled());\n\
# $this->assertSame(0, $transport2HandlerThatFails->getTimesCalled());\n# $this->assertCount(0,\
\ $failureTransport1->getMessagesWaitingToBeReceived());\n# $this->assertCount(0,\
\ $failureTransport2->getMessagesWaitingToBeReceived());\n# \n# // Receive the\
\ message from \"transport2\"\n# $throwable = $runWorker('transport2');\n# $this->assertInstanceOf(HandlerFailedException::class,\
\ $throwable);\n# $this->assertSame(2, $transport1HandlerThatFails->getTimesCalled());\n\
# // handler for \"transport2\" is called\n# $this->assertSame(1, $transport2HandlerThatFails->getTimesCalled());\n\
# $this->assertCount(0, $failureTransport1->getMessagesWaitingToBeReceived());\n\
# // the failure transport \"the_failure_transport2\" has 1 new message failed\
\ from \"transport2\"\n# $this->assertCount(1, $failureTransport2->getMessagesWaitingToBeReceived());\n\
# \n# // Consume the failure message failed on \"transport2\"\n# $runWorker('the_failure_transport2');\n\
# $this->assertSame(2, $transport1HandlerThatFails->getTimesCalled());\n# // \"\
transport2\" handler is called again from the \"the_failed_transport2\" and it\
\ fails\n# $this->assertSame(2, $transport2HandlerThatFails->getTimesCalled());\n\
# $this->assertCount(0, $failureTransport1->getMessagesWaitingToBeReceived());\n\
# // After the message fails again, the message is discarded from the \"the_failure_transport2\"\
\n# $this->assertCount(0, $failureTransport2->getMessagesWaitingToBeReceived());\n\
# }\n# \n# public function testStampsAddedByMiddlewaresDontDisappearWhenDelayedMessageFails()\n\
# {\n# $transport1 = new DummyFailureTestSenderAndReceiver();\n# \n# $transports\
\ = [\n# 'transport1' => $transport1,\n# ];\n# \n# $locator = new Container();\n\
# \n# foreach ($transports as $transportName => $transport) {\n# $locator->set($transportName,\
\ $transport);\n# }\n# \n# $senderLocator = new SendersLocator([], $locator);\n\
# \n# $retryStrategyLocator = new Container();\n# $retryStrategyLocator->set('transport1',\
\ new MultiplierRetryStrategy(1));\n# \n# $syncHandlerThatFails = new DummyTestHandler(true);\n\
# \n# $middlewareStack = new \\ArrayIterator([\n# new AddBusNameStampMiddleware('some.bus'),\n\
# new DispatchAfterCurrentBusMiddleware(),\n# new SendMessageMiddleware($senderLocator),\n\
# ]);\n# \n# $bus = new MessageBus($middlewareStack);\n# \n# $transport1Handler\
\ = fn () => $bus->dispatch(new \\stdClass(), [new DispatchAfterCurrentBusStamp()]);\n\
# \n# $handlerLocator = new HandlersLocator([\n# DummyMessage::class => [new HandlerDescriptor($transport1Handler)],\n\
# \\stdClass::class => [new HandlerDescriptor($syncHandlerThatFails)],\n# ]);\n\
# \n# $middlewareStack->append(new HandleMessageMiddleware($handlerLocator));\n\
# \n# $dispatcher = new EventDispatcher();\n# \n# $dispatcher->addSubscriber(new\
\ SendFailedMessageForRetryListener($locator, $retryStrategyLocator));\n# $dispatcher->addSubscriber(new\
\ StopWorkerOnMessageLimitListener(1));\n# \n# $runWorker = function (string $transportName)\
\ use ($transports, $bus, $dispatcher): ?\\Throwable {\n# $throwable = null;\n\
# $failedListener = function (WorkerMessageFailedEvent $event) use (&$throwable)\
\ {\n# $throwable = $event->getThrowable();\n# };\n# $dispatcher->addListener(WorkerMessageFailedEvent::class,\
\ $failedListener);\n# \n# $worker = new Worker([$transportName => $transports[$transportName]],\
\ $bus, $dispatcher);\n# \n# $worker->run();\n# \n# $dispatcher->removeListener(WorkerMessageFailedEvent::class,\
\ $failedListener);\n# \n# return $throwable;\n# };\n# \n# // Simulate receive\
\ from external source\n# $transport1->send(new Envelope(new DummyMessage('API')));\n\
# \n# // Receive the message from \"transport1\"\n# $throwable = $runWorker('transport1');\n\
# \n# $this->assertInstanceOf(DelayedMessageHandlingException::class, $throwable,\
\ $throwable->getMessage());\n# $this->assertSame(1, $syncHandlerThatFails->getTimesCalled());\n\
# \n# $messagesWaiting = $transport1->getMessagesWaitingToBeReceived();\n# \n\
# // Stamps should not be dropped on message that's queued for retry\n# $this->assertCount(1,\
\ $messagesWaiting);\n# $this->assertSame('some.bus', $messagesWaiting[0]->last(BusNameStamp::class)?->getBusName());\n\
# }\n# \n# public function testStampsAddedByMiddlewaresDontDisappearWhenValidationFails()\n\
# {\n# $transport1 = new DummyFailureTestSenderAndReceiver();\n# \n# $transports\
\ = [\n# 'transport1' => $transport1,\n# ];\n# \n# $locator = new Container();\n\
# $locator->set('transport1', $transport1);\n# \n# $senderLocator = new SendersLocator([],\
\ $locator);\n# \n# $retryStrategyLocator = new Container();\n# $retryStrategyLocator->set('transport1',\
\ new MultiplierRetryStrategy(1));\n# \n# $violationList = new ConstraintViolationList([new\
\ ConstraintViolation('validation failed', null, [], null, null, null)]);\n# $validator\
\ = $this->createMock(ValidatorInterface::class);\n# $validator->expects($this->once())->method('validate')->willReturn($violationList);\n\
# \n# $middlewareStack = new \\ArrayIterator([\n# new AddBusNameStampMiddleware('some.bus'),\n\
# new ValidationMiddleware($validator),\n# new SendMessageMiddleware($senderLocator),\n\
# ]);\n# \n# $bus = new MessageBus($middlewareStack);\n# \n# $transport1Handler\
\ = fn () => $bus->dispatch(new \\stdClass(), [new DispatchAfterCurrentBusStamp()]);\n\
# \n# $handlerLocator = new HandlersLocator([\n# DummyMessage::class => [new HandlerDescriptor($transport1Handler)],\n\
# ]);\n# \n# $middlewareStack->append(new HandleMessageMiddleware($handlerLocator));\n\
# \n# $dispatcher = new EventDispatcher();\n# \n# $dispatcher->addSubscriber(new\
\ SendFailedMessageForRetryListener($locator, $retryStrategyLocator));\n# $dispatcher->addSubscriber(new\
\ StopWorkerOnMessageLimitListener(1));\n# \n# $runWorker = function (string $transportName)\
\ use ($transports, $bus, $dispatcher): ?\\Throwable {\n# $throwable = null;\n\
# $failedListener = function (WorkerMessageFailedEvent $event) use (&$throwable)\
\ {\n# $throwable = $event->getThrowable();\n# };\n# $dispatcher->addListener(WorkerMessageFailedEvent::class,\
\ $failedListener);\n# \n# $worker = new Worker([$transportName => $transports[$transportName]],\
\ $bus, $dispatcher);\n# \n# $worker->run();\n# \n# $dispatcher->removeListener(WorkerMessageFailedEvent::class,\
\ $failedListener);\n# \n# return $throwable;\n# };\n# \n# // Simulate receive\
\ from external source\n# $transport1->send(new Envelope(new DummyMessage('API')));\n\
# \n# // Receive the message from \"transport1\"\n# $throwable = $runWorker('transport1');\n\
# \n# $this->assertInstanceOf(ValidationFailedException::class, $throwable, $throwable->getMessage());\n\
# \n# $messagesWaiting = $transport1->getMessagesWaitingToBeReceived();\n# \n\
# // Stamps should not be dropped on message that's queued for retry\n# $this->assertCount(1,\
\ $messagesWaiting);\n# $this->assertSame('some.bus', $messagesWaiting[0]->last(BusNameStamp::class)?->getBusName());\n\
# }\n# }\n# \n# class DummyFailureTestSenderAndReceiver implements ReceiverInterface,\
\ SenderInterface\n# {\n# private array $messagesWaiting = [];\n# \n# public function\
\ get(): iterable\n# {\n# $message = array_shift($this->messagesWaiting);\n# \n\
# if (null === $message) {\n# return [];\n# }\n# \n# return [$message];\n# }\n\
# \n# public function ack(Envelope $envelope): void\n# {\n# }\n# \n# public function\
\ reject(Envelope $envelope): void\n# {\n# }\n# \n# public function send(Envelope\
\ $envelope): Envelope\n# {\n# $this->messagesWaiting[] = $envelope;\n# \n# return\
\ $envelope;\n# }\n# \n# /**\n# * @return Envelope[]"
- name: __construct
visibility: public
parameters:
- name: shouldThrow
comment: null
- name: __invoke
visibility: public
parameters: []
comment: null
- name: getTimesCalled
visibility: public
parameters: []
comment: null
- name: setShouldThrow
visibility: public
parameters:
- name: shouldThrow
comment: null
traits:
- PHPUnit\Framework\TestCase
- Psr\Log\NullLogger
- Symfony\Component\DependencyInjection\Container
- Symfony\Component\DependencyInjection\ServiceLocator
- Symfony\Component\EventDispatcher\EventDispatcher
- Symfony\Component\Messenger\Envelope
- Symfony\Component\Messenger\Event\WorkerMessageFailedEvent
- Symfony\Component\Messenger\EventListener\AddErrorDetailsStampListener
- Symfony\Component\Messenger\EventListener\SendFailedMessageForRetryListener
- Symfony\Component\Messenger\EventListener\SendFailedMessageToFailureTransportListener
- Symfony\Component\Messenger\EventListener\StopWorkerOnMessageLimitListener
- Symfony\Component\Messenger\Exception\DelayedMessageHandlingException
- Symfony\Component\Messenger\Exception\HandlerFailedException
- Symfony\Component\Messenger\Exception\ValidationFailedException
- Symfony\Component\Messenger\Handler\HandlerDescriptor
- Symfony\Component\Messenger\Handler\HandlersLocator
- Symfony\Component\Messenger\MessageBus
- Symfony\Component\Messenger\Middleware\AddBusNameStampMiddleware
- Symfony\Component\Messenger\Middleware\DispatchAfterCurrentBusMiddleware
- Symfony\Component\Messenger\Middleware\FailedMessageProcessingMiddleware
- Symfony\Component\Messenger\Middleware\HandleMessageMiddleware
- Symfony\Component\Messenger\Middleware\SendMessageMiddleware
- Symfony\Component\Messenger\Middleware\ValidationMiddleware
- Symfony\Component\Messenger\Retry\MultiplierRetryStrategy
- Symfony\Component\Messenger\Stamp\BusNameStamp
- Symfony\Component\Messenger\Stamp\DispatchAfterCurrentBusStamp
- Symfony\Component\Messenger\Stamp\ErrorDetailsStamp
- Symfony\Component\Messenger\Stamp\SentToFailureTransportStamp
- Symfony\Component\Messenger\Tests\Fixtures\DummyMessage
- Symfony\Component\Messenger\Transport\Receiver\ReceiverInterface
- Symfony\Component\Messenger\Transport\Sender\SenderInterface
- Symfony\Component\Messenger\Transport\Sender\SendersLocator
- Symfony\Component\Messenger\Worker
- Symfony\Component\Validator\ConstraintViolation
- Symfony\Component\Validator\ConstraintViolationList
- Symfony\Component\Validator\Validator\ValidatorInterface
interfaces:
- ReceiverInterface