Closed
Description
Description
Current implementation forces applications to define which transport(s) to use with a class in configuration file. It would be great if it was possible to dictate transport in business logic.
This might be a common problem for other developers, that's why I thought it would be good to make it part of symfony/messenger instead of overriding a Symfony class in business application.
Example
Before:
framework:
messenger:
transports:
normal_queue: ...
important_queue: ...
routing:
App\Message\SmsNotification': normal_queue
<?php
// comments, trademark, use statements and constructor removed for PR description
namespace Symfony\Component\Messenger\Transport\Sender;
class SendersLocator implements SendersLocatorInterface
{
public function getSenders(Envelope $envelope): iterable
{
$seen = [];
foreach (HandlersLocator::listTypes($envelope) as $type) {
foreach ($this->sendersMap[$type] ?? [] as $senderAlias) {
if (!\in_array($senderAlias, $seen, true)) {
if (!$this->sendersLocator->has($senderAlias)) {
throw new RuntimeException(sprintf('Invalid senders configuration: sender "%s" is not in the senders locator.', $senderAlias));
}
$seen[] = $senderAlias;
$sender = $this->sendersLocator->get($senderAlias);
yield $senderAlias => $sender;
}
}
}
}
}
After:
<?php
// comments, trademark, use statements and constructor removed for PR description
namespace Symfony\Component\Messenger\Transport\Sender;
class SendersLocator implements SendersLocatorInterface
{
public function getSenders(Envelope $envelope): iterable
{
if ($envelope->all(OverrideSendersStamp::class)) {
$overrideSendersStamp = $envelope->last(OverrideSendersStamp::class);
foreach ($overrideSendersStamp->getSenders() as $senderAlias) {
yield from $this->getSenderFromAlias($senderAlias);
}
} else {
$seen = [];
foreach (HandlersLocator::listTypes($envelope) as $type) {
foreach ($this->sendersMap[$type] ?? [] as $senderAlias) {
if (!\in_array($senderAlias, $seen, true)) {
$seen[] = $senderAlias;
yield from $this->getSenderFromAlias($senderAlias);
}
}
}
}
}
private function getSenderFromAlias(string $senderAlias): iterable
{
if (!$this->sendersLocator->has($senderAlias)) {
throw new RuntimeException(sprintf('Invalid senders configuration: sender "%s" is not in the senders locator.', $senderAlias));
}
$sender = $this->sendersLocator->get($senderAlias);
yield $senderAlias => $sender;
}
}
In applications, developers can use it like below
// This will be in normal_queue
$bus->dispatch(new SmsNotification('...'));
For overridden behaviour:
// This will be in important_queue
$bus->dispatch(new Envelope(new SmsNotification('...'), [
new OverrideSendersStamp(['important_queue'])
]));