-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Messenger] Add Transport attribute to configure message to transport mapping #41179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
467ab2c
to
0c31db6
Compare
b45b3aa
to
7651b34
Compare
Hey! I think @tyx has recently worked with this code. Maybe they can help review this? Cheers! Carsonbot |
src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php
Outdated
Show resolved
Hide resolved
a1503a0
to
91b3e8f
Compare
Added some changes:
|
77baba0
to
9b09951
Compare
sorry, i meant file config should overwrite attributes. So we have a way to opt-out from whatever the code is telling us. without attributes AND file config, we could maybe inherit the parent attributes (as we inherit file config). Meaning we also have a way to opt out from the parent attr. |
So lets say we have:
Do you expect it to be sent to
Why would we want to opt-out from parent attributes? I mean we don't have an option to opt-out from MessageInterface routing (see example above) currently, at least that I'm aware of, do we? |
Yes. I see i made a thinking error. Each type either derives from file config, or if unavailable, attributes. Meaning we can opt-out from the parent by also specifying file config for that type. |
What's the way to configure a transport right now using a DI tag? |
At the moment we have this code in FrameworkExtension. It reads routing from the config and passes the message-to-senders map to the SendersLocator (where I did changes). $messageToSendersMapping = [];
foreach ($config['routing'] as $message => $messageConfiguration) {
if ('*' !== $message && !class_exists($message) && !interface_exists($message, false)) {
throw new LogicException(sprintf('Invalid Messenger routing configuration: class or interface "%s" not found.', $message));
}
foreach ($messageConfiguration['senders'] as $sender) {
if (!isset($senderReferences[$sender])) {
throw new LogicException(sprintf('Invalid Messenger routing configuration: the "%s" class is being routed to a sender called "%s". This is not a valid transport or service id.', $message, $sender));
}
}
$messageToSendersMapping[$message] = $messageConfiguration['senders'];
}
$sendersServiceLocator = ServiceLocatorTagPass::register($container, $senderReferences);
$container->getDefinition('messenger.senders_locator')
->replaceArgument(0, $messageToSendersMapping)
->replaceArgument(1, $sendersServiceLocator)
; There's also code, that uses |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nicolas-grekas this is indeed about routing-messages-to-a-transport
my main motivation here is, to have a single list of things; the messages in code. Or reduce config management if you like :)
src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php
Outdated
Show resolved
Hide resolved
7f82bba
to
3c36432
Compare
@shiftby Is this still planed for 5.4? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like this. I think a common pattern is for apps to create Sync
/Async
marker interfaces to simplify routing rules.
src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php
Outdated
Show resolved
Hide resolved
@shiftby, I took the liberty of rebasing and cleaning this up - hope we can get this in 6.1. @ro0NL, @nicolas-grekas, could we get a fresh review? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would totally use this :)
src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php
Outdated
Show resolved
Hide resolved
$typeSenderAliases = $this->getSendersFromAttributes($type); | ||
} | ||
|
||
$senderAliases = array_merge($senderAliases, $typeSenderAliases); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand it correctly, IF even one real route exists for the message (something in $this->sendersMap[$type]
), then we do NOT also add the #[Transport]
senders? So basically any config would override the attribute?
I think that is... probably the correct behavior. But what about the *
catch-all route in messenger.yaml
(or an interface)? I'm wondering if someone will have the use-case where they generally use the attribute, but then they decide to, in addition to the transport in each class, route all messages (or all messages for an interface) to a 2nd transport via the routing config in messenger.yaml
.
So, I'm conflicted on this point.
$attributeInstance = $attribute->newInstance(); | ||
|
||
return $attributeInstance->name; | ||
}, $attributes); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unfortunate to need to do this at runtime (and not compile time). But as messages are not services... or tagged in any way, there is no way for us to collect the attribute information at container build time. So 👍 for this approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is indeed unfortunate. Any clever ideas? I understand it depends, but is there a non-negligible performance impact to processing the attributes at runtime?
I made a little change to allow sub-classes of the #[\Attribute(\Attribute::TARGET_CLASS)]
class HighPriority extends Transport
{
public function __construct()
{
parent::__construct('high_priority');
}
}
#[HighPriority]
class MyMessage {} |
I opened #57506 which is kind of a duplicate of this issue (sorry for the noise). It seems that there wasn't any activity here for a year or so, what's the status here? |
I'm sorry if I hijacked this, but #57507 is ready. This PR is stalled for approximatly a year, and it will cause conflict if merged over the most recent Symfony version, this would mean rewrite pretty much everything. Should we close this PR? |
…sage routing (pounard) This PR was merged into the 7.2 branch. Discussion ---------- [Messenger] Introduce `#[AsMessage]` attribute for message routing | Q | A | ------------- | --- | Branch? | 7.2 | Bug fix? | no | New feature? | yes | Deprecations? | no | Issues | Fix #57506 | License | MIT Basic implementation of #57506. * Adds the `Symfony\Component\Messenger\Attribute\AsMessage` attribute, with the `$transport` parameter which can be `string` or `array`. * Implement runtime routing in `Symfony\Component\Messenger\Transport\Sender\SendersLocator`. Rationale: * Messages are not services, it cannot be computed during container compilation. * Reflection is very fast, it shouldn't be significant for performances, yet I don't have measured it yet. * YAML configuration and `Symfony\Component\Messenger\Stamp\TransportNamesStamp` will always override the attribute values, allowing users to change hardcoded routing on a per-environment basis. * This is the simplest implementation I could think of for discussion. Links and references: * #33912 where the discussion started, 5 years ago. * #49143 closed PR that was doing the same, but at compile time, rejected because the actual doctrine is that messages should never be services. * #41179 is stilled opened, and awaiting for modifications, but it was written for an earlier version of Symfony and is inactive for a year or so, yet messenger code has evolved since, and this PR will never merge as-is, it requires to be fully rewrote, reason why I opened this new one. Commits ------- d652842 feature #57506 [Messenger] introduce AsMessage attribute for message routing
…sage routing (pounard) This PR was merged into the 7.2 branch. Discussion ---------- [Messenger] Introduce `#[AsMessage]` attribute for message routing | Q | A | ------------- | --- | Branch? | 7.2 | Bug fix? | no | New feature? | yes | Deprecations? | no | Issues | Fix #57506 | License | MIT Basic implementation of #57506. * Adds the `Symfony\Component\Messenger\Attribute\AsMessage` attribute, with the `$transport` parameter which can be `string` or `array`. * Implement runtime routing in `Symfony\Component\Messenger\Transport\Sender\SendersLocator`. Rationale: * Messages are not services, it cannot be computed during container compilation. * Reflection is very fast, it shouldn't be significant for performances, yet I don't have measured it yet. * YAML configuration and `Symfony\Component\Messenger\Stamp\TransportNamesStamp` will always override the attribute values, allowing users to change hardcoded routing on a per-environment basis. * This is the simplest implementation I could think of for discussion. Links and references: * symfony/symfony#33912 where the discussion started, 5 years ago. * symfony/symfony#49143 closed PR that was doing the same, but at compile time, rejected because the actual doctrine is that messages should never be services. * symfony/symfony#41179 is stilled opened, and awaiting for modifications, but it was written for an earlier version of Symfony and is inactive for a year or so, yet messenger code has evolved since, and this PR will never merge as-is, it requires to be fully rewrote, reason why I opened this new one. Commits ------- d65284239f feature #57506 [Messenger] introduce AsMessage attribute for message routing
Let us know if #57507 isn't enough. Thanks @maxim-dovydenok for pushing this forward. |
This PR adds
Transport
attribute to configure Message->Transport mapping. This attribute is read in the SenderLocator class.Using this attribute it will be possible to configure transport for the message in the message class file instead of messenger.yaml.