10000 [Messenger] Message cannot be bare strings or empty, message type cannot be an arbitrary string · Issue #33369 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content
[Messenger] Message cannot be bare strings or empty, message type cannot be an arbitrary string #33369
Closed
@pounard

Description

@pounard

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.prepare for 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 called type (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 StringMessage or ArbitraryMessage class with tow methods getValue(): string or getContents(): string and getType(): string method 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.prepare to App\Domain\Order\Event\OrderPrepareMessage back and forth, this map would need to be configurable at the project level by either a raw YAML configuration in the config/ 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 a MessageTypeStamp or directly setting a type property on the StringMessage class,
  • 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 ?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0