Skip to content

Commit

Permalink
bug #51508 [Messenger] Fix routing to multiple fallback transports (v…
Browse files Browse the repository at this point in the history
…altzu)

This PR was merged into the 6.3 branch.

Discussion
----------

[Messenger] Fix routing to multiple fallback transports

| Q             | A
| ------------- | ---
| Branch?       | 6.3
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| License       | MIT

The change made in symfony/symfony#48121 means that it's not possible to route into multiple transport as fallback like

```yaml
framework:
  messenger:
    routing:
      My\Message\*: [async, audit]
```

F.e. the message `My\Message\ToBeSentToTwoSenders` would only reach `async`.

The comment in the code mentions

> if other senders already matched **with previous types**, skip the senders bound to the fallback

While in reality how it works is

> if other senders already matched, skip the senders bound to the fallback

After the changes in this MR it works as mentioned in the original comment, meaning it does not skip for the same type, but routes to all transports for that type.

---

This is not a BC break because anyone who has more than one transport in a wildcard rule has never received anything matching the wildcard on other than the 1st transport – so only if you had a misconfiguration in the first place you're affected.

Commits
-------

76f2433fa9 Fix routing to multiple fallback transports
  • Loading branch information
nicolas-grekas committed Sep 29, 2023
2 parents ea2e2c5 + ed542ee commit fb29632
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 8 deletions.
6 changes: 4 additions & 2 deletions Tests/Transport/Sender/SendersLocatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,19 @@ public function testSendersMapWithFallback()
{
$firstSender = $this->createMock(SenderInterface::class);
$secondSender = $this->createMock(SenderInterface::class);
$thirdSender = $this->createMock(SenderInterface::class);
$sendersLocator = $this->createContainer([
'first' => $firstSender,
'second' => $secondSender,
'third' => $thirdSender,
]);
$locator = new SendersLocator([
DummyMessage::class => ['first'],
'*' => ['second'],
'*' => ['second', 'third'],
], $sendersLocator);

$this->assertSame(['first' => $firstSender], iterator_to_array($locator->getSenders(new Envelope(new DummyMessage('a')))), 'Unexpected senders for configured message');
$this->assertSame(['second' => $secondSender], iterator_to_array($locator->getSenders(new Envelope(new SecondMessage()))), 'Unexpected senders for unconfigured message');
$this->assertSame(['second' => $secondSender, 'third' => $thirdSender], iterator_to_array($locator->getSenders(new Envelope(new SecondMessage()))), 'Unexpected senders for unconfigured message');
}

private function createContainer(array $senders): ContainerInterface
Expand Down
12 changes: 6 additions & 6 deletions Transport/Sender/SendersLocator.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ public function getSenders(Envelope $envelope): iterable
$seen = [];

foreach (HandlersLocator::listTypes($envelope) as $type) {
foreach ($this->sendersMap[$type] ?? [] as $senderAlias) {
if (str_ends_with($type, '*') && $seen) {
// the '*' acts as a fallback, if other senders already matched
// with previous types, skip the senders bound to the fallback
continue;
}
if (str_ends_with($type, '*') && $seen) {
// the '*' acts as a fallback, if other senders already matched
// with previous types, skip the senders bound to the fallback
continue;
}

foreach ($this->sendersMap[$type] ?? [] as $senderAlias) {
if (!\in_array($senderAlias, $seen, true)) {
$seen[] = $senderAlias;

Expand Down

0 comments on commit fb29632

Please sign in to comment.