From d65284239fc73158f86eb3198bf9d1095eadf659 Mon Sep 17 00:00:00 2001 From: Pierre Rineau Date: Mon, 24 Jun 2024 13:12:00 +0200 Subject: [PATCH] feature #57506 [Messenger] introduce AsMessage attribute for message routing --- .../Messenger/Attribute/AsMessage.php | 29 +++++++++++ src/Symfony/Component/Messenger/CHANGELOG.md | 1 + .../Fixtures/DummyMessageWithAttribute.php | 19 +++++++ .../Transport/Sender/SendersLocatorTest.php | 52 +++++++++++++++++++ .../Transport/Sender/SendersLocator.php | 30 +++++++++++ 5 files changed, 131 insertions(+) create mode 100644 src/Symfony/Component/Messenger/Attribute/AsMessage.php create mode 100644 src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php diff --git a/src/Symfony/Component/Messenger/Attribute/AsMessage.php b/src/Symfony/Component/Messenger/Attribute/AsMessage.php new file mode 100644 index 0000000000000..bc60ec032bff9 --- /dev/null +++ b/src/Symfony/Component/Messenger/Attribute/AsMessage.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Attribute; + +/** + * Attribute for configuring message routing. + * + * @author Pierre Rineau pierre.rineau@processus.org> + */ +#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)] +class AsMessage +{ + public function __construct( + /** + * Name of the transports to which the message should be routed. + */ + public null|string|array $transport = null, + ) { + } +} diff --git a/src/Symfony/Component/Messenger/CHANGELOG.md b/src/Symfony/Component/Messenger/CHANGELOG.md index d8f4705562eec..bdb161a7f3048 100644 --- a/src/Symfony/Component/Messenger/CHANGELOG.md +++ b/src/Symfony/Component/Messenger/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 7.2 --- + * Add `#[AsMessage]` attribute with `$transport` parameter for message routing * Add `--format` option to the `messenger:stats` command 7.1 diff --git a/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php b/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php new file mode 100644 index 0000000000000..ceb85833b478b --- /dev/null +++ b/src/Symfony/Component/Messenger/Tests/Fixtures/DummyMessageWithAttribute.php @@ -0,0 +1,19 @@ +message; + } +} diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php index 3aafa82f73d73..ef81920af8917 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php @@ -17,6 +17,8 @@ use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Stamp\TransportNamesStamp; use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage; +use Symfony\Component\Messenger\Tests\Fixtures\DummyMessageInterface; +use Symfony\Component\Messenger\Tests\Fixtures\DummyMessageWithAttribute; use Symfony\Component\Messenger\Tests\Fixtures\SecondMessage; use Symfony\Component\Messenger\Transport\Sender\SenderInterface; use Symfony\Component\Messenger\Transport\Sender\SendersLocator; @@ -53,6 +55,56 @@ public function testItReturnsTheSenderBasedOnTransportNamesStamp() $this->assertSame([], iterator_to_array($locator->getSenders(new Envelope(new SecondMessage())))); } + public function testItReturnsTheSenderBasedOnAsMessageAttribute() + { + $firstSender = $this->createMock(SenderInterface::class); + $secondSender = $this->createMock(SenderInterface::class); + $otherSender = $this->createMock(SenderInterface::class); + $sendersLocator = $this->createContainer([ + 'first_sender' => $firstSender, + 'second_sender' => $secondSender, + 'other_sender' => $otherSender, + ]); + $locator = new SendersLocator([], $sendersLocator); + + $this->assertSame(['first_sender' => $firstSender, 'second_sender' => $secondSender], iterator_to_array($locator->getSenders(new Envelope(new DummyMessageWithAttribute('a'))))); + $this->assertSame([], iterator_to_array($locator->getSenders(new Envelope(new SecondMessage())))); + } + + public function testAsMessageAttributeIsOverridenByTransportNamesStamp() + { + $firstSender = $this->createMock(SenderInterface::class); + $secondSender = $this->createMock(SenderInterface::class); + $otherSender = $this->createMock(SenderInterface::class); + $sendersLocator = $this->createContainer([ + 'first_sender' => $firstSender, + 'second_sender' => $secondSender, + 'other_sender' => $otherSender, + ]); + $locator = new SendersLocator([], $sendersLocator); + + $this->assertSame(['other_sender' => $otherSender], iterator_to_array($locator->getSenders(new Envelope(new DummyMessageWithAttribute('a'), [new TransportNamesStamp(['other_sender'])])))); + $this->assertSame([], iterator_to_array($locator->getSenders(new Envelope(new SecondMessage())))); + } + + public function testAsMessageAttributeIsOverridenByUserConfiguration() + { + $firstSender = $this->createMock(SenderInterface::class); + $secondSender = $this->createMock(SenderInterface::class); + $otherSender = $this->createMock(SenderInterface::class); + $sendersLocator = $this->createContainer([ + 'first_sender' => $firstSender, + 'second_sender' => $secondSender, + 'other_sender' => $otherSender, + ]); + $locator = new SendersLocator([ + DummyMessageInterface::class => ['other_sender'], + ], $sendersLocator); + + $this->assertSame(['other_sender' => $otherSender], iterator_to_array($locator->getSenders(new Envelope(new DummyMessageWithAttribute('a'))))); + $this->assertSame([], iterator_to_array($locator->getSenders(new Envelope(new SecondMessage())))); + } + public function testSendersMapWithFallback() { $firstSender = $this->createMock(SenderInterface::class); diff --git a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php index 22850d8b089a6..9f711d91e5a96 100644 --- a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php +++ b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Messenger\Transport\Sender; use Psr\Container\ContainerInterface; +use Symfony\Component\Messenger\Attribute\AsMessage; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Exception\RuntimeException; use Symfony\Component\Messenger\Handler\HandlersLocator; @@ -45,6 +46,7 @@ public function getSenders(Envelope $envelope): iterable } $seen = []; + $found = false; foreach (HandlersLocator::listTypes($envelope) as $type) { if (str_ends_with($type, '*') && $seen) { @@ -58,9 +60,37 @@ public function getSenders(Envelope $envelope): iterable $seen[] = $senderAlias; yield from $this->getSenderFromAlias($senderAlias); + $found = true; } } } + + // Let the configuration-driven map upper override message attributes, + // this allows environment-specific configuration overriding hardcoded + // transport name. + if ($found) { + return; + } + + foreach ($this->getTransportNamesFromAttribute($envelope) as $senderAlias) { + yield from $this->getSenderFromAlias($senderAlias); + } + } + + private function getTransportNamesFromAttribute(Envelope $envelope): array + { + $transports = []; + $message = $envelope->getMessage(); + + foreach ((new \ReflectionClass($message))->getAttributes(AsMessage::class, \ReflectionAttribute::IS_INSTANCEOF) as $refAttr) { + $asMessage = $refAttr->newInstance(); + + if ($asMessage->transport) { + $transports = \array_merge($transports, (array) $asMessage->transport); + } + } + + return $transports; } private function getSenderFromAlias(string $senderAlias): iterable pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy