-
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
Description
There are a variety of existing message brokers, and don't know all of them, I have to admit that my knowledge is still young and limited on this topic, but it seems that in theory in most of them, a message is anything but a simple byte stream.
In a way, I do understand (if my assumptions are correct) why the choice of always typing messages using a valid PHP class so you can type and route them to their handlers very easily. But in way, it looses flexibility and prevent interoperability in heterogeneous existing environments:
-
you can't just receive messages that have names such as
order.preparefor example, which in the end could actually quite happen with some message brokers, if I read correctly AMQP spec for example, there's an arbitrary yet in the protocol message property which is calledtype(I might be wrong on this one, spec is not an easy beast to read), -
you can't send them either, or you will need to write a custom middleware, but it would be sad to let end user do this on every project they need it,
-
you could receive messages which are bare strings, no content-type, no serialization,
-
you can't send them either (a.k.a. "Hello, World!" for example).
As soon as you enter an existing environment based upon a message broker that as any of those specificity, you cannot use the Symfony messenger within.
This is a feature request, but also a support question at the same time, is it going to be supported ?
I could see many ways to allow this:
- allow messages to be bare strings but wrap them in a default
StringMessageorArbitraryMessageclass with tow methodsgetValue(): stringorgetContents(): stringandgetType(): stringmethod when receiving them, - ask for the developer to wrap the message by itself in that very same class when sending them,
- plug a type to class map middleware that would convert
order.preparetoApp\Domain\Order\Event\OrderPrepareMessageback and forth, this map would need to be configurable at the project level by either a raw YAML configuration in theconfig/folder or using annotations on the messages classes, such as@Message(type="order.prepare")for example, or any other easy to use way of letting the application developper defining it (personally I don't love annotations, and in the projects I work on, we don't use them at all), - give a way for the end-user developer to pass the arbitrary type (for when it's a not a class but a bare string message) to the
dispatch()method, either by an additional parameter or using something like aMessageTypeStampor directly setting atypeproperty on theStringMessageclass, - message type is not a universally thing amongst message brokers, but let those that don't support it fail when sending or ignore when receiving, the application developer must be in control of these aspects, not the messenger component itself.
That's my 2 cents, I have no extensive knowledge about message brokers and message buses, but it seems rather sane to consider that messages are nothing more than bare byte streams when they're dispatched, and not all messages will end up being nice hydratable JSON or XML.
For example, it seems totally fine, IMHO to send such message within a bus and expect a business consuming application to be able to process it:
Headers/Properties/Attributes (name it using your message broker own semantics):
content-type: application/octet-stream
type: product.delete
Content:
12
Where 12 is an identifier, but as a message broker, I don't care what it is, it is the consumer responsibility to know what to do about that, and maybe messenger should not be that strict upon internal routing within the application, some handler could just receive untyped messages and process them with instanceof statements.
May be an additional handler interface could also carry a handle($message, string $type) method ?