-
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
Description
The messenger component works pretty good by default if you send messenges with the messenger component and also consume them this way. But if you need to consume messages from a third-party there are several problems which requires alot of thought to make this work.
Serialization does not work - let keep track in #33912
External messages do not have the headers/content that sf serializer requires. External messages are likely not encoded using php serialize
so the default PhpSerializer
does not work. But also the SymfonySerializer
can't work because external messages won't have the type
header to know which class to deserialize to. This can be solved using a custom serializer. So maybe this issue is only about documenting an example custom Serializer to fix this gotcha. Having a solution that works by default could be possible using a GenericMessage class. See #31230 Or we implement some default JSON Serializer that uses \JsonSerializable
and custom callback like $message = $messageClass::fromJson($encodedEnvelope['body'])
. So people would only need to configure the default message class of a transport and fromJson
. No need to implement a whole custom serializer which requires handling headers etc.
Retry does not work - fixed by #32053
As said above, external messages do not have the SF messenger headers. This also means, they do not have any Stamps. Without the SentStamp
, the retry logic that is enabled by default, does not work. You get the following warning.
16:11:12 WARNING [messenger] Message will not be retried because the SentStamp is missing and so the target sender cannot be determined.
We need to find a solution that does not require the SentStamp. Using the SentStamp for retry seems strange anyway. You can route a single message to several transports. But the retry logic just uses the last sender for redelivery which is arbitrary.
The solution I see: In the Worker just use the current transport also for redelivery. That should cover 99% of all cases and would be the same behavior as now. If somebody needs customization we could even introduce a retry_transport
config option on the transport. This way people could send retries to a different transport.
The current workaround is to write a custom transport that adds a fake SentStamp
when receiving messages.
Routing to correct bus does not work - fixed by #34247
The RouteableMessageBus
requires the BusNameStamp
to know which bus the messages should be dispatched to. So as soon as you have more than one bus, third-party messages can't be consumed without having to manually specify the bus option like bin/console messenger:consume mytransport --bus=mybus
every time. In general I don't think the --bus
option is a good thing. If you accidentally specify the wrong bus, hell can break lose. I'd prefer a config option on the transport level where you can specify the bus that all messages from this transport should go. It can default to null which uses the current BusNameStamp
logic so people using SF messenger to send and receive messages won't have to worry about this. For consuming third-party messages you just set this config option. Then we don't even need the --bus
option on the worker anymore IMO. It's just too error-prone and repetitive as you need to specify each time you run the worker. Also the option that shouldn't be used can confuse people.
Current workaround is also to add a BusNameStamp
in a custom transport.