diff --git a/src/Symfony/Bridge/Doctrine/Messenger/DoctrineClearEntityManagerMiddleware.php b/src/Symfony/Bridge/Doctrine/Messenger/DoctrineClearEntityManagerMiddleware.php index 16aec310c6fcf..0bef9be641aa7 100644 --- a/src/Symfony/Bridge/Doctrine/Messenger/DoctrineClearEntityManagerMiddleware.php +++ b/src/Symfony/Bridge/Doctrine/Messenger/DoctrineClearEntityManagerMiddleware.php @@ -14,7 +14,7 @@ use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Middleware\StackInterface; -use Symfony\Component\Messenger\Stamp\ReceivedStamp; +use Symfony\Component\Messenger\Stamp\ConsumedByWorkerStamp; /** * Clears entity manager after calling all handlers. @@ -28,7 +28,7 @@ protected function handleForManager(EntityManagerInterface $entityManager, Envel try { return $stack->next()->handle($envelope, $stack); } finally { - if (null !== $envelope->last(ReceivedStamp::class)) { + if (null !== $envelope->last(ConsumedByWorkerStamp::class)) { $entityManager->clear(); } } diff --git a/src/Symfony/Bridge/Doctrine/Messenger/DoctrineCloseConnectionMiddleware.php b/src/Symfony/Bridge/Doctrine/Messenger/DoctrineCloseConnectionMiddleware.php index b5160d13aa2cc..b0a96e05daa33 100644 --- a/src/Symfony/Bridge/Doctrine/Messenger/DoctrineCloseConnectionMiddleware.php +++ b/src/Symfony/Bridge/Doctrine/Messenger/DoctrineCloseConnectionMiddleware.php @@ -14,7 +14,7 @@ use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Middleware\StackInterface; -use Symfony\Component\Messenger\Stamp\ReceivedStamp; +use Symfony\Component\Messenger\Stamp\ConsumedByWorkerStamp; /** * Closes connection and therefore saves number of connections. @@ -30,7 +30,7 @@ protected function handleForManager(EntityManagerInterface $entityManager, Envel return $stack->next()->handle($envelope, $stack); } finally { - if (null !== $envelope->last(ReceivedStamp::class)) { + if (null !== $envelope->last(ConsumedByWorkerStamp::class)) { $connection->close(); } } diff --git a/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php b/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php index a5c2531afe59d..f6febb2a7e673 100644 --- a/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php +++ b/src/Symfony/Bridge/Doctrine/Messenger/DoctrinePingConnectionMiddleware.php @@ -14,7 +14,7 @@ use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Middleware\StackInterface; -use Symfony\Component\Messenger\Stamp\ReceivedStamp; +use Symfony\Component\Messenger\Stamp\ConsumedByWorkerStamp; /** * Checks whether the connection is still open or reconnects otherwise. @@ -25,7 +25,7 @@ class DoctrinePingConnectionMiddleware extends AbstractDoctrineMiddleware { protected function handleForManager(EntityManagerInterface $entityManager, Envelope $envelope, StackInterface $stack): Envelope { - if (null !== $envelope->last(ReceivedStamp::class)) { + if (null !== $envelope->last(ConsumedByWorkerStamp::class)) { $this->pingConnection($entityManager); } diff --git a/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrineClearEntityManagerMiddlewareTest.php b/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrineClearEntityManagerMiddlewareTest.php index 4b53fef761371..580cd3fb8e39b 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrineClearEntityManagerMiddlewareTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrineClearEntityManagerMiddlewareTest.php @@ -16,7 +16,7 @@ use Symfony\Bridge\Doctrine\Messenger\DoctrineClearEntityManagerMiddleware; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException; -use Symfony\Component\Messenger\Stamp\ReceivedStamp; +use Symfony\Component\Messenger\Stamp\ConsumedByWorkerStamp; use Symfony\Component\Messenger\Test\Middleware\MiddlewareTestCase; class DoctrineClearEntityManagerMiddlewareTest extends MiddlewareTestCase @@ -36,7 +36,7 @@ public function testMiddlewareClearEntityManager() $middleware = new DoctrineClearEntityManagerMiddleware($managerRegistry, 'default'); $envelope = new Envelope(new \stdClass(), [ - new ReceivedStamp('async'), + new ConsumedByWorkerStamp(), ]); $middleware->handle($envelope, $this->getStackMock()); } diff --git a/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrineCloseConnectionMiddlewareTest.php b/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrineCloseConnectionMiddlewareTest.php index 0f44049bb6a82..5a0b7a7452f7a 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrineCloseConnectionMiddlewareTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrineCloseConnectionMiddlewareTest.php @@ -17,7 +17,7 @@ use Symfony\Bridge\Doctrine\Messenger\DoctrineCloseConnectionMiddleware; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException; -use Symfony\Component\Messenger\Stamp\ReceivedStamp; +use Symfony\Component\Messenger\Stamp\ConsumedByWorkerStamp; use Symfony\Component\Messenger\Test\Middleware\MiddlewareTestCase; class DoctrineCloseConnectionMiddlewareTest extends MiddlewareTestCase @@ -51,7 +51,7 @@ public function testMiddlewareCloseConnection() ; $envelope = new Envelope(new \stdClass(), [ - new ReceivedStamp('async'), + new ConsumedByWorkerStamp(), ]); $this->middleware->handle($envelope, $this->getStackMock()); } diff --git a/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php b/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php index 1b09189cc9368..446d63013d79f 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php @@ -17,7 +17,7 @@ use Symfony\Bridge\Doctrine\Messenger\DoctrinePingConnectionMiddleware; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException; -use Symfony\Component\Messenger\Stamp\ReceivedStamp; +use Symfony\Component\Messenger\Stamp\ConsumedByWorkerStamp; use Symfony\Component\Messenger\Test\Middleware\MiddlewareTestCase; class DoctrinePingConnectionMiddlewareTest extends MiddlewareTestCase @@ -58,7 +58,7 @@ public function testMiddlewarePingOk() ; $envelope = new Envelope(new \stdClass(), [ - new ReceivedStamp('async'), + new ConsumedByWorkerStamp(), ]); $this->middleware->handle($envelope, $this->getStackMock()); } @@ -75,7 +75,7 @@ public function testMiddlewarePingResetEntityManager() ; $envelope = new Envelope(new \stdClass(), [ - new ReceivedStamp('async'), + new ConsumedByWorkerStamp(), ]); $this->middleware->handle($envelope, $this->getStackMock()); } diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 0578a4be8e23b..75eaffdc5a7b4 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -29,7 +29,7 @@ "symfony/dependency-injection": "^3.4|^4.0|^5.0", "symfony/form": "^4.4|^5.0", "symfony/http-kernel": "^3.4|^4.0|^5.0", - "symfony/messenger": "^4.3|^5.0", + "symfony/messenger": "^4.4|^5.0", "symfony/property-access": "^3.4|^4.0|^5.0", "symfony/property-info": "^3.4|^4.0|^5.0", "symfony/proxy-manager-bridge": "^3.4|^4.0|^5.0", diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 0dae2eebcdafe..246828f4107f4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1775,27 +1775,18 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder $container->setAlias('messenger.default_serializer', $config['serializer']['default_serializer']); } - $senderReferences = []; - $syncTransports = []; + $senderAliases = []; $transportRetryReferences = []; foreach ($config['transports'] as $name => $transport) { $serializerId = $transport['serializer'] ?? 'messenger.default_serializer'; - if (0 === strpos($transport['dsn'], 'sync://')) { - $syncTransports[] = $name; - } else { - $transportDefinition = (new Definition(TransportInterface::class)) - ->setFactory([new Reference('messenger.transport_factory'), 'createTransport']) - ->setArguments([$transport['dsn'], $transport['options'] + ['transport_name' => $name], new Reference($serializerId)]) - ->addTag('messenger.receiver', ['alias' => $name]) - ; - $container->setDefinition($transportId = 'messenger.transport.'.$name, $transportDefinition); - - // alias => service_id - $senderReferences[$name] = new Reference($transportId); - // service_id => service_id - $senderReferences[$transportId] = new Reference($transportId); - } + $transportDefinition = (new Definition(TransportInterface::class)) + ->setFactory([new Reference('messenger.transport_factory'), 'createTransport']) + ->setArguments([$transport['dsn'], $transport['options'] + ['transport_name' => $name], new Reference($serializerId)]) + ->addTag('messenger.receiver', ['alias' => $name]) + ; + $container->setDefinition($transportId = 'messenger.transport.'.$name, $transportDefinition); + $senderAliases[$name] = $transportId; if (null !== $transport['retry_strategy']['service']) { $transportRetryReferences[$name] = new Reference($transport['retry_strategy']['service']); @@ -1813,25 +1804,30 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder } } + $senderReferences = []; + // alias => service_id + foreach ($senderAliases as $alias => $serviceId) { + $senderReferences[$alias] = new Reference($serviceId); + } + // service_id => service_id + foreach ($senderAliases as $serviceId) { + $senderReferences[$serviceId] = new Reference($serviceId); + } + $messageToSendersMapping = []; foreach ($config['routing'] as $message => $messageConfiguration) { if ('*' !== $message && !class_exists($message) && !interface_exists($message, false)) { throw new LogicException(sprintf('Invalid Messenger routing configuration: class or interface "%s" not found.', $message)); } - // filter out "sync" senders - $realSenders = []; + // make sure senderAliases contains all senders foreach ($messageConfiguration['senders'] as $sender) { - if (isset($senderReferences[$sender])) { - $realSenders[] = $sender; - } elseif (!\in_array($sender, $syncTransports, true)) { + if (!isset($senderReferences[$sender])) { throw new LogicException(sprintf('Invalid Messenger routing configuration: the "%s" class is being routed to a sender called "%s". This is not a valid transport or service id.', $message, $sender)); } } - if ($realSenders) { - $messageToSendersMapping[$message] = $realSenders; - } + $messageToSendersMapping[$message] = $messageConfiguration['senders']; } $container->getDefinition('messenger.senders_locator') diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.xml index 6debf4a3c2fed..2284dd796363f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.xml @@ -75,6 +75,11 @@ + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_sync_transport.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_sync_transport.php deleted file mode 100644 index 09f8c53fc32bc..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_sync_transport.php +++ /dev/null @@ -1,15 +0,0 @@ -loadFromExtension('framework', [ - 'messenger' => [ - 'transports' => [ - 'amqp' => 'amqp://localhost/%2f/messages', - 'sync' => 'sync://', - ], - 'routing' => [ - 'Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\DummyMessage' => ['amqp'], - 'Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\SecondMessage' => ['sync'], - 'Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\FooMessage' => ['amqp', 'sync'], - ], - ], -]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_sync_transport.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_sync_transport.xml deleted file mode 100644 index 2345cc2342e5b..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_sync_transport.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_sync_transport.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_sync_transport.yml deleted file mode 100644 index f7b4fdefe04a8..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_sync_transport.yml +++ /dev/null @@ -1,10 +0,0 @@ -framework: - messenger: - transports: - amqp: 'amqp://localhost/%2f/messages' - sync: 'sync://' - - routing: - 'Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\DummyMessage': amqp - 'Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\SecondMessage': sync - 'Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\FooMessage': [amqp, sync] diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index fe49656032afc..1e97f61d7cbc9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -16,8 +16,6 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension; use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\DummyMessage; -use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\FooMessage; -use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\SecondMessage; use Symfony\Bundle\FrameworkBundle\Tests\TestCase; use Symfony\Bundle\FullStack; use Symfony\Component\Cache\Adapter\AdapterInterface; @@ -784,17 +782,6 @@ public function testMessengerInvalidTransportRouting() $this->createContainerFromFile('messenger_routing_invalid_transport'); } - public function testMessengerSyncTransport() - { - $container = $this->createContainerFromFile('messenger_sync_transport'); - $senderLocatorDefinition = $container->getDefinition('messenger.senders_locator'); - - $sendersMapping = $senderLocatorDefinition->getArgument(0); - $this->assertEquals(['amqp'], $sendersMapping[DummyMessage::class]); - $this->assertArrayNotHasKey(SecondMessage::class, $sendersMapping); - $this->assertEquals(['amqp'], $sendersMapping[FooMessage::class]); - } - public function testTranslator() { $container = $this->createContainerFromFile('full'); diff --git a/src/Symfony/Component/Messenger/CHANGELOG.md b/src/Symfony/Component/Messenger/CHANGELOG.md index 68d180d0e7ff7..30e195f7ee635 100644 --- a/src/Symfony/Component/Messenger/CHANGELOG.md +++ b/src/Symfony/Component/Messenger/CHANGELOG.md @@ -4,7 +4,6 @@ CHANGELOG 4.4.0 ----- - * [BC BREAK] The `SyncTransport` and `SyncTransportFactory` classes were removed. * Deprecated passing a `ContainerInterface` instance as first argument of the `ConsumeMessagesCommand` constructor, pass a `RoutableMessageBus` instance instead. * Added support for auto trimming of Redis streams. diff --git a/src/Symfony/Component/Messenger/Stamp/ConsumedByWorkerStamp.php b/src/Symfony/Component/Messenger/Stamp/ConsumedByWorkerStamp.php new file mode 100644 index 0000000000000..3ae37ba6ad230 --- /dev/null +++ b/src/Symfony/Component/Messenger/Stamp/ConsumedByWorkerStamp.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Stamp; + +/** + * A marker that this message was consumed by a worker process. + */ +class ConsumedByWorkerStamp implements NonSendableStampInterface +{ +} diff --git a/src/Symfony/Component/Messenger/Tests/Transport/AmqpExt/AmqpExtIntegrationTest.php b/src/Symfony/Component/Messenger/Tests/Transport/AmqpExt/AmqpExtIntegrationTest.php index d62e3014dab99..9fddc0646cdfd 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/AmqpExt/AmqpExtIntegrationTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/AmqpExt/AmqpExtIntegrationTest.php @@ -174,7 +174,8 @@ public function testItReceivesSignals() Get envelope with message: Symfony\Component\Messenger\Tests\Fixtures\DummyMessage with stamps: [ "Symfony\\Component\\Messenger\\Transport\\AmqpExt\\AmqpReceivedStamp", - "Symfony\\Component\\Messenger\\Stamp\\ReceivedStamp" + "Symfony\\Component\\Messenger\\Stamp\\ReceivedStamp", + "Symfony\\Component\\Messenger\\Stamp\\ConsumedByWorkerStamp" ] Done. diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Sync/SyncTransportFactoryTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Sync/SyncTransportFactoryTest.php new file mode 100644 index 0000000000000..021c7ae9706a4 --- /dev/null +++ b/src/Symfony/Component/Messenger/Tests/Transport/Sync/SyncTransportFactoryTest.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Tests\Transport\AmqpExt; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Messenger\MessageBusInterface; +use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface; +use Symfony\Component\Messenger\Transport\Sync\SyncTransport; +use Symfony\Component\Messenger\Transport\Sync\SyncTransportFactory; + +class SyncTransportFactoryTest extends TestCase +{ + public function testCreateTransport() + { + $serializer = $this->createMock(SerializerInterface::class); + $bus = $this->createMock(MessageBusInterface::class); + $factory = new SyncTransportFactory($bus); + $transport = $factory->createTransport('sync://', [], $serializer); + $this->assertInstanceOf(SyncTransport::class, $transport); + } +} diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Sync/SyncTransportTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Sync/SyncTransportTest.php new file mode 100644 index 0000000000000..13549e27582a1 --- /dev/null +++ b/src/Symfony/Component/Messenger/Tests/Transport/Sync/SyncTransportTest.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Tests\Transport\AmqpExt; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Messenger\MessageBusInterface; +use Symfony\Component\Messenger\Stamp\ReceivedStamp; +use Symfony\Component\Messenger\Transport\Sync\SyncTransport; + +class SyncTransportTest extends TestCase +{ + public function testSend() + { + $bus = $this->createMock(MessageBusInterface::class); + $bus->expects($this->once()) + ->method('dispatch') + ->with($this->callback(function ($arg) { + $this->assertInstanceOf(Envelope::class, $arg); + + return true; + })) + ->willReturnArgument(0); + $message = new \stdClass(); + $envelope = new Envelope($message); + $transport = new SyncTransport($bus); + $envelope = $transport->send($envelope); + + $this->assertSame($message, $envelope->getMessage()); + $this->assertNotNull($envelope->last(ReceivedStamp::class)); + } +} diff --git a/src/Symfony/Component/Messenger/Tests/WorkerTest.php b/src/Symfony/Component/Messenger/Tests/WorkerTest.php index 9a09c0a04a333..c4d6c782af294 100644 --- a/src/Symfony/Component/Messenger/Tests/WorkerTest.php +++ b/src/Symfony/Component/Messenger/Tests/WorkerTest.php @@ -21,6 +21,7 @@ use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException; use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Messenger\Retry\RetryStrategyInterface; +use Symfony\Component\Messenger\Stamp\ConsumedByWorkerStamp; use Symfony\Component\Messenger\Stamp\ReceivedStamp; use Symfony\Component\Messenger\Stamp\RedeliveryStamp; use Symfony\Component\Messenger\Stamp\SentStamp; @@ -47,11 +48,11 @@ public function testWorkerDispatchTheReceivedMessage() $bus = $this->getMockBuilder(MessageBusInterface::class)->getMock(); $bus->expects($this->at(0))->method('dispatch')->with( - $envelope = new Envelope($apiMessage, [new ReceivedStamp('transport')]) + $envelope = new Envelope($apiMessage, [new ReceivedStamp('transport'), new ConsumedByWorkerStamp()]) )->willReturn($envelope); $bus->expects($this->at(1))->method('dispatch')->with( - $envelope = new Envelope($ipaMessage, [new ReceivedStamp('transport')]) + $envelope = new Envelope($ipaMessage, [new ReceivedStamp('transport'), new ConsumedByWorkerStamp()]) )->willReturn($envelope); $worker = new Worker(['transport' => $receiver], $bus); @@ -69,7 +70,7 @@ public function testWorkerDoesNotWrapMessagesAlreadyWrappedWithReceivedMessage() { $envelope = new Envelope(new DummyMessage('API')); $receiver = new DummyReceiver([[$envelope]]); - $envelope = $envelope->with(new ReceivedStamp('transport')); + $envelope = $envelope->with(new ReceivedStamp('transport'), new ConsumedByWorkerStamp()); $bus = $this->getMockBuilder(MessageBusInterface::class)->getMock(); $bus->expects($this->at(0))->method('dispatch')->with($envelope)->willReturn($envelope); diff --git a/src/Symfony/Component/Messenger/Transport/Sync/SyncTransport.php b/src/Symfony/Component/Messenger/Transport/Sync/SyncTransport.php new file mode 100644 index 0000000000000..67af9039139db --- /dev/null +++ b/src/Symfony/Component/Messenger/Transport/Sync/SyncTransport.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Transport\Sync; + +use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Messenger\Exception\InvalidArgumentException; +use Symfony\Component\Messenger\MessageBusInterface; +use Symfony\Component\Messenger\Stamp\ReceivedStamp; +use Symfony\Component\Messenger\Stamp\SentStamp; +use Symfony\Component\Messenger\Transport\TransportInterface; + +/** + * Transport that immediately marks messages as received and dispatches for handling. + * + * @author Ryan Weaver + */ +class SyncTransport implements TransportInterface +{ + private $messageBus; + + public function __construct(MessageBusInterface $messageBus) + { + $this->messageBus = $messageBus; + } + + public function get(): iterable + { + throw new InvalidArgumentException('You cannot receive messages from the Messenger SyncTransport.'); + } + + public function stop(): void + { + throw new InvalidArgumentException('You cannot call stop() on the Messenger SyncTransport.'); + } + + public function ack(Envelope $envelope): void + { + throw new InvalidArgumentException('You cannot call ack() on the Messenger SyncTransport.'); + } + + public function reject(Envelope $envelope): void + { + throw new InvalidArgumentException('You cannot call reject() on the Messenger SyncTransport.'); + } + + public function send(Envelope $envelope): Envelope + { + /** @var SentStamp|null $sentStamp */ + $sentStamp = $envelope->last(SentStamp::class); + $alias = null === $sentStamp ? 'sync' : ($sentStamp->getSenderAlias() ?: $sentStamp->getSenderClass()); + + $envelope = $envelope->with(new ReceivedStamp($alias)); + + return $this->messageBus->dispatch($envelope); + } +} diff --git a/src/Symfony/Component/Messenger/Transport/Sync/SyncTransportFactory.php b/src/Symfony/Component/Messenger/Transport/Sync/SyncTransportFactory.php new file mode 100644 index 0000000000000..1784bfb7979bb --- /dev/null +++ b/src/Symfony/Component/Messenger/Transport/Sync/SyncTransportFactory.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Transport\Sync; + +use Symfony\Component\Messenger\MessageBusInterface; +use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface; +use Symfony\Component\Messenger\Transport\TransportFactoryInterface; +use Symfony\Component\Messenger\Transport\TransportInterface; + +/** + * @author Ryan Weaver + */ +class SyncTransportFactory implements TransportFactoryInterface +{ + private $messageBus; + + public function __construct(MessageBusInterface $messageBus) + { + $this->messageBus = $messageBus; + } + + public function createTransport(string $dsn, array $options, SerializerInterface $serializer): TransportInterface + { + return new SyncTransport($this->messageBus); + } + + public function supports(string $dsn, array $options): bool + { + return 0 === strpos($dsn, 'sync://'); + } +} diff --git a/src/Symfony/Component/Messenger/Worker.php b/src/Symfony/Component/Messenger/Worker.php index 41a589fae25d3..1765fbec2a0a9 100644 --- a/src/Symfony/Component/Messenger/Worker.php +++ b/src/Symfony/Component/Messenger/Worker.php @@ -21,6 +21,7 @@ use Symfony\Component\Messenger\Exception\RejectRedeliveredMessageException; use Symfony\Component\Messenger\Exception\UnrecoverableExceptionInterface; use Symfony\Component\Messenger\Retry\RetryStrategyInterface; +use Symfony\Component\Messenger\Stamp\ConsumedByWorkerStamp; use Symfony\Component\Messenger\Stamp\DelayStamp; use Symfony\Component\Messenger\Stamp\ReceivedStamp; use Symfony\Component\Messenger\Stamp\RedeliveryStamp; @@ -132,7 +133,7 @@ private function handleMessage(Envelope $envelope, ReceiverInterface $receiver, ]; try { - $envelope = $this->bus->dispatch($envelope->with(new ReceivedStamp($transportName))); + $envelope = $this->bus->dispatch($envelope->with(new ReceivedStamp($transportName), new ConsumedByWorkerStamp())); } catch (\Throwable $throwable) { $rejectFirst = $throwable instanceof RejectRedeliveredMessageException; if ($rejectFirst) {