8000 [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

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

Closed
pounard opened this issue Aug 28, 2019 · 3 comments

Comments

@pounard
Copy link
Contributor
pounard commented Aug 28, 2019

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 ?

@pounard pounard changed the title [Messenger] Message can be bare strings or empty, message type cannot be an arbitrary string [Messenger] Message cannot be bare strings or empty, message type cannot be an arbitrary string Aug 28, 2019
@pounard
Copy link
Contributor Author
pounard commented Aug 29, 2019

Related to #33368 - Likely a duplicate of #31230

@pounard
Copy link
Contributor Author
pounard commented Aug 29, 2019

Answer from @Tobion #31230 (comment)

I don't think having a custom serializer does solve everything. Having a default fallback mechanism that just would propagate the raw string into a default class could be a nice thing to have in this component. It still would fail if there's no handler to deal with it, but it'd leave the opportunity for handlers to target this class and do whatever they want to with, without needing to override the serializer at the project level.

@Nyholm
Copy link
Member
Nyholm commented Jan 26, 2020

Interesting. I see how this simplicity could be appealing for the user. But it will make things way more complicated. Example: How do you do routing?

I also fail to see the business case of sending empty strings =)

The workaround is simple if one would like to send arbitrary data, one just create a class like:

class MyMessage{
  private $data;
  public function __construct($data) {
    $this->data = $data;
  }
  public function getData() {
     return $this->data;
  }
}

@Nyholm Nyholm closed this as completed Jan 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants
0