Skip to content

Commit 1a4a5d5

Browse files
committed
feature #39306 [Messenger] Add TransportNamesStamp to change the transport while dispatching a message (asilelik, fabpot)
This PR was merged into the 6.2 branch. Discussion ---------- [Messenger] Add `TransportNamesStamp` to change the transport while dispatching a message | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | Fix #38200, Fix #39306 | License | MIT | Doc PR | symfony/symfony-docs#... (Will be added after PR discussion about implementation) This feature will allow developers to choose transport layer while dispatching a message. Normally, we define transport layer in configuration. As a result, developer doesn't have any power to modify it after the deployment. This PR aims to allow overriding already defined transport layer for a message and rerouting it to different transport per dispatch request. If newly added stamp is not used, default configuration will be used for choosing transport. Since I've added a new stamp, there shouldn't be any BC change. Commits ------- f526af0 [Messenger] Rename some classes b501e67 Add functionality for choosing transport while dispatching message
2 parents e1435f6 + f526af0 commit 1a4a5d5

File tree

5 files changed

+98
-6
lines changed

5 files changed

+98
-6
lines changed

src/Symfony/Component/Messenger/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
---
66

77
* Add new `messenger:stats` command that return a list of transports with their "to be processed" message count
8+
* Add `TransportNamesStamp` to change the transport while dispatching a message
89

910
6.1
1011
---
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Messenger\Stamp;
13+
14+
/**
15+
* Stamp used to override the transport names specified in the Messenger routing configuration file.
16+
*/
17+
final class TransportNamesStamp implements StampInterface
18+
{
19+
/**
20+
* @param string[] $transports Transport names to be used for the message
21+
*/
22+
public function __construct(private array $transports)
23+
{
24+
}
25+
26+
public function getTransportNames(): array
27+
{
28+
return $this->transports;
29+
}
30+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Messenger\Tests\Stamp;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Messenger\Stamp\TransportNamesStamp;
16+
17+
class TransportNamesStampTest extends TestCase
18+
{
19+
public function testGetSenders()
20+
{
21+
$configuredSenders = ['first_transport', 'second_transport', 'other_transport'];
22+
$stamp = new TransportNamesStamp($configuredSenders);
23+
$stampSenders = $stamp->getTransportNames();
24+
$this->assertEquals(\count($configuredSenders), \count($stampSenders));
25+
26+
foreach ($configuredSenders as $key => $sender) {
27+
$this->assertSame($sender, $stampSenders[$key]);
28+
}
29+
}
30+
}

src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Psr\Container\ContainerInterface;
1616
use Symfony\Component\Messenger\Envelope;
17+
use Symfony\Component\Messenger\Stamp\TransportNamesStamp;
1718
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
1819
use Symfony\Component\Messenger\Tests\Fixtures\SecondMessage;
1920
use Symfony\Component\Messenger\Transport\Sender\SenderInterface;
@@ -35,6 +36,22 @@ public function testItReturnsTheSenderBasedOnTheMessageClass()
3536
$this->assertSame([], iterator_to_array($locator->getSenders(new Envelope(new SecondMessage()))));
3637
}
3738

39+
public function testItReturnsTheSenderBasedOnTransportNamesStamp()
40+
{
41+
$mySender = $this->createMock(SenderInterface::class);
42+
$otherSender = $this->createMock(SenderInterface::class);
43+
$sendersLocator = $this->createContainer([
44+
'my_sender' => $mySender,
45+
'other_sender' => $otherSender,
46+
]);
47+
$locator = new SendersLocator([
48+
DummyMessage::class => ['my_sender'],
49+
], $sendersLocator);
50+
51+
$this->assertSame(['other_sender' => $otherSender], iterator_to_array($locator->getSenders(new Envelope(new DummyMessage('a'), [new TransportNamesStamp(['other_sender'])]))));
52+
$this->assertSame([], iterator_to_array($locator->getSenders(new Envelope(new SecondMessage()))));
53+
}
54+
3855
private function createContainer(array $senders): ContainerInterface
3956
{
4057
$container = $this->createMock(ContainerInterface::class);

src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\Messenger\Envelope;
1616
use Symfony\Component\Messenger\Exception\RuntimeException;
1717
use Symfony\Component\Messenger\Handler\HandlersLocator;
18+
use Symfony\Component\Messenger\Stamp\TransportNamesStamp;
1819

1920
/**
2021
* Maps a message to a list of senders.
@@ -41,20 +42,33 @@ public function __construct(array $sendersMap, ContainerInterface $sendersLocato
4142
*/
4243
public function getSenders(Envelope $envelope): iterable
4344
{
45+
if ($envelope->all(TransportNamesStamp::class)) {
46+
foreach ($envelope->last(TransportNamesStamp::class)->getTransportNames() as $senderAlias) {
47+
yield from $this->getSenderFromAlias($senderAlias);
48+
}
49+
50+
return;
51+
}
52+
4453
$seen = [];
4554

4655
foreach (HandlersLocator::listTypes($envelope) as $type) {
4756
foreach ($this->sendersMap[$type] ?? [] as $senderAlias) {
4857
if (!\in_array($senderAlias, $seen, true)) {
49-
if (!$this->sendersLocator->has($senderAlias)) {
50-
throw new RuntimeException(sprintf('Invalid senders configuration: sender "%s" is not in the senders locator.', $senderAlias));
51-
}
52-
5358
$seen[] = $senderAlias;
54-
$sender = $this->sendersLocator->get($senderAlias);
55-
yield $senderAlias => $sender;
59+
60+
yield from $this->getSenderFromAlias($senderAlias);
5661
}
5762
}
5863
}
5964
}
65+
66+
private function getSenderFromAlias(string $senderAlias): iterable
67+
{
68+
if (!$this->sendersLocator->has($senderAlias)) {
69+
throw new RuntimeException(sprintf('Invalid senders configuration: sender "%s" is not in the senders locator.', $senderAlias));
70+
}
71+
72+
yield $senderAlias => $this->sendersLocator->get($senderAlias);
73+
}
6074
}

0 commit comments

Comments
 (0)