From 70d6d27eaa4fcf181364228264d38d31be74a19a Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Thu, 21 Mar 2024 13:58:47 +0100 Subject: [PATCH 1/2] Introduce SelfStampableInterface --- .../Message/SelfStampableInterface.php | 22 ++++++++++++++++++ .../Component/Messenger/MessageBus.php | 5 ++++ .../Fixtures/SelfStampableDummyMessage.php | 23 +++++++++++++++++++ .../Messenger/Tests/MessageBusTest.php | 9 ++++++++ 4 files changed, 59 insertions(+) create mode 100644 src/Symfony/Component/Messenger/Message/SelfStampableInterface.php create mode 100644 src/Symfony/Component/Messenger/Tests/Fixtures/SelfStampableDummyMessage.php diff --git a/src/Symfony/Component/Messenger/Message/SelfStampableInterface.php b/src/Symfony/Component/Messenger/Message/SelfStampableInterface.php new file mode 100644 index 0000000000000..016867ae0677d --- /dev/null +++ b/src/Symfony/Component/Messenger/Message/SelfStampableInterface.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Message; + +use Symfony\Component\Messenger\Stamp\StampInterface; + +interface SelfStampableInterface +{ + /** + * @return array + */ + public function getStamps(): array; +} diff --git a/src/Symfony/Component/Messenger/MessageBus.php b/src/Symfony/Component/Messenger/MessageBus.php index 69eb370594f65..3dcfea6567372 100644 --- a/src/Symfony/Component/Messenger/MessageBus.php +++ b/src/Symfony/Component/Messenger/MessageBus.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Messenger; +use Symfony\Component\Messenger\Message\SelfStampableInterface; use Symfony\Component\Messenger\Middleware\MiddlewareInterface; use Symfony\Component\Messenger\Middleware\StackMiddleware; @@ -53,6 +54,10 @@ public function getIterator(): \Traversable public function dispatch(object $message, array $stamps = []): Envelope { + if ($message instanceof SelfStampableInterface) { + $stamps = array_merge($message->getStamps(), $stamps); + } + $envelope = Envelope::wrap($message, $stamps); $middlewareIterator = $this->middlewareAggregate->getIterator(); diff --git a/src/Symfony/Component/Messenger/Tests/Fixtures/SelfStampableDummyMessage.php b/src/Symfony/Component/Messenger/Tests/Fixtures/SelfStampableDummyMessage.php new file mode 100644 index 0000000000000..ce38c03fa6eca --- /dev/null +++ b/src/Symfony/Component/Messenger/Tests/Fixtures/SelfStampableDummyMessage.php @@ -0,0 +1,23 @@ +message; + } + + public function getStamps(): array + { + return [new DelayStamp(1)]; + } +} diff --git a/src/Symfony/Component/Messenger/Tests/MessageBusTest.php b/src/Symfony/Component/Messenger/Tests/MessageBusTest.php index 0d6f36de51a4f..f21e1b32875d8 100644 --- a/src/Symfony/Component/Messenger/Tests/MessageBusTest.php +++ b/src/Symfony/Component/Messenger/Tests/MessageBusTest.php @@ -22,6 +22,7 @@ use Symfony\Component\Messenger\Stamp\ReceivedStamp; use Symfony\Component\Messenger\Tests\Fixtures\AnEnvelopeStamp; use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage; +use Symfony\Component\Messenger\Tests\Fixtures\SelfStampableDummyMessage; class MessageBusTest extends TestCase { @@ -133,6 +134,14 @@ public function testItAddsTheStampsToEnvelope() $this->assertCount(2, $finalEnvelope->all()); } + public function testSelfStampableMessage() + { + $finalEnvelope = (new MessageBus())->dispatch(new SelfStampableDummyMessage(''), [new DelayStamp(5), new BusNameStamp('bar')]); + $this->assertCount(2, $finalEnvelope->all()); + $this->assertCount(2, $finalEnvelope->all()[DelayStamp::class]); + $this->assertSame(5, $finalEnvelope->last(DelayStamp::class)->getDelay()); + } + public static function provideConstructorDataStucture(): iterable { yield 'iterator' => [new \ArrayObject([ From 8f0da1ca98d70389e52c650eb519d0a45c931b59 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Fri, 7 Feb 2025 10:11:22 +0100 Subject: [PATCH 2/2] Rework --- .../FrameworkExtension.php | 3 +- .../Resources/config/messenger.php | 3 ++ .../FrameworkExtensionTestCase.php | 2 + src/Symfony/Component/Messenger/CHANGELOG.md | 1 + .../Message/SelfStampableInterface.php | 5 +- .../Component/Messenger/MessageBus.php | 5 -- .../AddSelfStampableStampsMiddleware.php | 35 +++++++++++++ .../Fixtures/SelfStampableDummyMessage.php | 2 +- .../Messenger/Tests/MessageBusTest.php | 9 ---- .../AddSelfStampableStampsMiddlewareTest.php | 49 +++++++++++++++++++ 10 files changed, 97 insertions(+), 17 deletions(-) create mode 100644 src/Symfony/Component/Messenger/Middleware/AddSelfStampableStampsMiddleware.php create mode 100644 src/Symfony/Component/Messenger/Tests/Middleware/AddSelfStampableStampsMiddlewareTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 9ee0f0f43441a..e0824121a274b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -2300,6 +2300,7 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder $defaultMiddleware = [ 'before' => [ + ['id' => 'add_self_stampable_stamps_middleware'], ['id' => 'add_bus_name_stamp_middleware'], ['id' => 'reject_redelivered_message_middleware'], ['id' => 'dispatch_after_current_bus'], @@ -2325,7 +2326,7 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder $defaultMiddleware['after'][1]['arguments'] = [$bus['default_middleware']['allow_no_handlers']]; // argument to add_bus_name_stamp_middleware - $defaultMiddleware['before'][0]['arguments'] = [$busId]; + $defaultMiddleware['before'][1]['arguments'] = [$busId]; $middleware = array_merge($defaultMiddleware['before'], $middleware, $defaultMiddleware['after']); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php index 8798d5f2e5e3e..f9f00a551c405 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php @@ -25,6 +25,7 @@ use Symfony\Component\Messenger\EventListener\StopWorkerOnRestartSignalListener; use Symfony\Component\Messenger\Handler\RedispatchMessageHandler; use Symfony\Component\Messenger\Middleware\AddBusNameStampMiddleware; +use Symfony\Component\Messenger\Middleware\AddSelfStampableStampsMiddleware; use Symfony\Component\Messenger\Middleware\DeduplicateMiddleware; use Symfony\Component\Messenger\Middleware\DispatchAfterCurrentBusMiddleware; use Symfony\Component\Messenger\Middleware\FailedMessageProcessingMiddleware; @@ -92,6 +93,8 @@ service('lock.factory'), ]) + ->set('messenger.middleware.add_self_stampable_stamps_middleware', AddSelfStampableStampsMiddleware::class) + ->set('messenger.middleware.add_bus_name_stamp_middleware', AddBusNameStampMiddleware::class) ->abstract() diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php index fdc586cc922ba..b194c992ec42e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -1064,6 +1064,7 @@ public function testMessengerWithMultipleBusesWithoutDeduplicateMiddleware() $this->assertTrue($container->has('messenger.bus.commands')); $this->assertSame([], $container->getDefinition('messenger.bus.commands')->getArgument(0)); $this->assertEquals([ + ['id' => 'add_self_stampable_stamps_middleware'], ['id' => 'add_bus_name_stamp_middleware', 'arguments' => ['messenger.bus.commands']], ['id' => 'reject_redelivered_message_middleware'], ['id' => 'dispatch_after_current_bus'], @@ -1104,6 +1105,7 @@ public function testMessengerWithMultipleBusesWithDeduplicateMiddleware() $this->assertTrue($container->has('messenger.bus.commands')); $this->assertSame([], $container->getDefinition('messenger.bus.commands')->getArgument(0)); $this->assertEquals([ + ['id' => 'add_self_stampable_stamps_middleware'], ['id' => 'add_bus_name_stamp_middleware', 'arguments' => ['messenger.bus.commands']], ['id' => 'reject_redelivered_message_middleware'], ['id' => 'dispatch_after_current_bus'], diff --git a/src/Symfony/Component/Messenger/CHANGELOG.md b/src/Symfony/Component/Messenger/CHANGELOG.md index b7973518fe41d..a97257dbbc8d4 100644 --- a/src/Symfony/Component/Messenger/CHANGELOG.md +++ b/src/Symfony/Component/Messenger/CHANGELOG.md @@ -7,6 +7,7 @@ CHANGELOG * Add `CloseableTransportInterface` to allow closing the transport * Add `SentForRetryStamp` that identifies whether a failed message was sent for retry * Add `Symfony\Component\Messenger\Middleware\DeduplicateMiddleware` and `Symfony\Component\Messenger\Stamp\DeduplicateStamp` + * Add `Symfony\Component\Messenger\Middleware\AddSelfStampableStampsMiddleware` and `Symfony\Component\Messenger\Message\SelfStampableInterface` 7.2 --- diff --git a/src/Symfony/Component/Messenger/Message/SelfStampableInterface.php b/src/Symfony/Component/Messenger/Message/SelfStampableInterface.php index 016867ae0677d..ab0c9257c763b 100644 --- a/src/Symfony/Component/Messenger/Message/SelfStampableInterface.php +++ b/src/Symfony/Component/Messenger/Message/SelfStampableInterface.php @@ -16,7 +16,10 @@ interface SelfStampableInterface { /** + * List of stamps which will be automatically added to the envelope, + * if there is no other stamp of the same class already set. + * * @return array */ - public function getStamps(): array; + public function getDefaultStamps(): array; } diff --git a/src/Symfony/Component/Messenger/MessageBus.php b/src/Symfony/Component/Messenger/MessageBus.php index 3dcfea6567372..69eb370594f65 100644 --- a/src/Symfony/Component/Messenger/MessageBus.php +++ b/src/Symfony/Component/Messenger/MessageBus.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Messenger; -use Symfony\Component\Messenger\Message\SelfStampableInterface; use Symfony\Component\Messenger\Middleware\MiddlewareInterface; use Symfony\Component\Messenger\Middleware\StackMiddleware; @@ -54,10 +53,6 @@ public function getIterator(): \Traversable public function dispatch(object $message, array $stamps = []): Envelope { - if ($message instanceof SelfStampableInterface) { - $stamps = array_merge($message->getStamps(), $stamps); - } - $envelope = Envelope::wrap($message, $stamps); $middlewareIterator = $this->middlewareAggregate->getIterator(); diff --git a/src/Symfony/Component/Messenger/Middleware/AddSelfStampableStampsMiddleware.php b/src/Symfony/Component/Messenger/Middleware/AddSelfStampableStampsMiddleware.php new file mode 100644 index 0000000000000..c9c4f7f882c0b --- /dev/null +++ b/src/Symfony/Component/Messenger/Middleware/AddSelfStampableStampsMiddleware.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Middleware; + +use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Messenger\Message\SelfStampableInterface; + +/** + * Automatically add stamps from the SelfStampableInterface. + */ +class AddSelfStampableStampsMiddleware implements MiddlewareInterface +{ + public function handle(Envelope $envelope, StackInterface $stack): Envelope + { + $message = $envelope->getMessage(); + if ($message instanceof SelfStampableInterface) { + foreach ($message->getDefaultStamps() as $stamp) { + if (null === $envelope->last($stamp::class)) { + $envelope = $envelope->with($stamp); + } + } + } + + return $stack->next()->handle($envelope, $stack); + } +} diff --git a/src/Symfony/Component/Messenger/Tests/Fixtures/SelfStampableDummyMessage.php b/src/Symfony/Component/Messenger/Tests/Fixtures/SelfStampableDummyMessage.php index ce38c03fa6eca..dce60744d671e 100644 --- a/src/Symfony/Component/Messenger/Tests/Fixtures/SelfStampableDummyMessage.php +++ b/src/Symfony/Component/Messenger/Tests/Fixtures/SelfStampableDummyMessage.php @@ -16,7 +16,7 @@ public function getMessage(): string return $this->message; } - public function getStamps(): array + public function getDefaultStamps(): array { return [new DelayStamp(1)]; } diff --git a/src/Symfony/Component/Messenger/Tests/MessageBusTest.php b/src/Symfony/Component/Messenger/Tests/MessageBusTest.php index f21e1b32875d8..0d6f36de51a4f 100644 --- a/src/Symfony/Component/Messenger/Tests/MessageBusTest.php +++ b/src/Symfony/Component/Messenger/Tests/MessageBusTest.php @@ -22,7 +22,6 @@ use Symfony\Component\Messenger\Stamp\ReceivedStamp; use Symfony\Component\Messenger\Tests\Fixtures\AnEnvelopeStamp; use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage; -use Symfony\Component\Messenger\Tests\Fixtures\SelfStampableDummyMessage; class MessageBusTest extends TestCase { @@ -134,14 +133,6 @@ public function testItAddsTheStampsToEnvelope() $this->assertCount(2, $finalEnvelope->all()); } - public function testSelfStampableMessage() - { - $finalEnvelope = (new MessageBus())->dispatch(new SelfStampableDummyMessage(''), [new DelayStamp(5), new BusNameStamp('bar')]); - $this->assertCount(2, $finalEnvelope->all()); - $this->assertCount(2, $finalEnvelope->all()[DelayStamp::class]); - $this->assertSame(5, $finalEnvelope->last(DelayStamp::class)->getDelay()); - } - public static function provideConstructorDataStucture(): iterable { yield 'iterator' => [new \ArrayObject([ diff --git a/src/Symfony/Component/Messenger/Tests/Middleware/AddSelfStampableStampsMiddlewareTest.php b/src/Symfony/Component/Messenger/Tests/Middleware/AddSelfStampableStampsMiddlewareTest.php new file mode 100644 index 0000000000000..978149e9e7e14 --- /dev/null +++ b/src/Symfony/Component/Messenger/Tests/Middleware/AddSelfStampableStampsMiddlewareTest.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Tests\Middleware; + +use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Messenger\Middleware\AddSelfStampableStampsMiddleware; +use Symfony\Component\Messenger\Stamp\DelayStamp; +use Symfony\Component\Messenger\Test\Middleware\MiddlewareTestCase; +use Symfony\Component\Messenger\Tests\Fixtures\SelfStampableDummyMessage; + +final class AddSelfStampableStampsMiddlewareTest extends MiddlewareTestCase +{ + public function testSelfStampableStampsMiddleware() + { + $message = new SelfStampableDummyMessage(''); + $envelope = new Envelope($message); + + $decorator = new AddSelfStampableStampsMiddleware(); + + $envelope = $decorator->handle($envelope, $this->getStackMock(true)); + + $delayStamp = $envelope->last(DelayStamp::class); + $this->assertNotNull($delayStamp); + $this->assertSame(1, $delayStamp->getDelay()); + } + + public function testSelfStampableStampsMiddlewareIfStampExists() + { + $message = new SelfStampableDummyMessage(''); + $envelope = new Envelope($message, [new DelayStamp(5)]); + + $decorator = new AddSelfStampableStampsMiddleware(); + + $envelope = $decorator->handle($envelope, $this->getStackMock(true)); + + $delayStamp = $envelope->last(DelayStamp::class); + $this->assertNotNull($delayStamp); + $this->assertSame(5, $delayStamp->getDelay()); + } +}