Description
Hi!
Currently, messages are "routes" to the transport by their class/type in config:
framework:
messenger:
transports:
async: '...'
async2: '...'
routing:
# Route your messages to the transports
'App\Message\CoolNotification': async
'App\Message\SmsNotification': [async, async2]
This has a few downsides:
-
If a message has 2 handlers, there is no way to send one handler to one transport (e.g.
async
) and another handle to another (e.g.sync)
. -
There is no way for a third-party to put a message into a bus and specify which transport it should go to. For example, the mailer might want a way to route all of its handled messages to a
mailer
transport that the user can then configure (there are a few missing pieces for this, but that's for a separate issue).
Proposal
Allow each handler to (optionally) specify what transport they should be sent to. This would be done via an interface + autowiring or via a tag:
class MyMessageHandler implements TransportAwareHandlerInterface
{
public function __invoke(MyMessage $myMessage)
{
}
public function getTransport()
{
return 'async';
}
}
Or via the tag:
services:
App\MessageHandler\MyMessageHandler:
tags:
- { name: messenger.message_handler, transport: async }
If the async
transport doesn't exist, an exception would be thrown.
This would become the main way that we recommend routing your messages, which means that we would recommend that the class->transport framework.messenger.routing
not be used, unless you want to send a message to a queue that will be handled outside of your app (and so, there is no sender).
This would play nicely with messages dispatched by 3rd party bundles. For example, supposes the mailer dispatches a SendMailMessage
, which is handled by its SendMailMessageHandler
. And the handler says it should go to a mail
transport (in another issue, we still need to allow 3rd party bundle to add transports & allow the user to map them, but ignore that for now). The user could then configure how it wants the mail
transport to work (e.g. async) AND attach a second handler to SendMailMessage
called LogSentMailMessagesHandler
, which they decide to handle on a sync
transport.
So, the question is: do we want to continue to route on a message-by-message basis? Or do we want to allow users to route on a handler-by-handler basis?