Symfony Messenger component documentation#9437
Symfony Messenger component documentation#9437javiereguiluz merged 15 commits intosymfony:masterfrom
Conversation
This PR was squashed before being merged into the 4.1-dev branch (closes #24411). Discussion ---------- [Messenger] Add a new Messenger component | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #24326 | License | MIT | Doc PR | symfony/symfony-docs#9437 As discussed in #24326. This PR is to help going forward with the discussions of having a Message component. # Resources | What | Where | --- | --- | Documentation | [In the PR](https://github.com/sroze/symfony/blob/add-message-component/src/Symfony/Component/Message/README.md) | Demo | [In `sroze/symfony-demo:message-component-demo`](https://github.com/sroze/symfony-demo/compare/message-component-demo) | [php-enqueue](https://github.com/php-enqueue/enqueue-dev) adapter | 1. Source: [In `sroze/enqueue-bridge`](https://github.com/sroze/enqueue-bridge) _(to be moved as `symfony/enqueue-bridge` I guess)_<br/>2. Demo: [In `sroze/symfony-demo:message-component-demo-with-enqueue`](sroze/symfony-demo@message-component-demo...sroze:message-component-demo-with-enqueue) | [Swarrot](https://github.com/swarrot/swarrot) adapter | **Outdated adapter, waiting for stabilization** 1. Source: [In `sroze/swarrot-bridge`](https://github.com/sroze/swarrot-bridge) _(to be moved as `symfony/swarrot-bridge` I guess)_<br/>2. Demo: [In `sroze/symfony-demo:message-component-demo-with-swarrot`](sroze/symfony-demo@message-component-demo...sroze:message-component-demo-with-swarrot) | [HTTP](https://github.com/sroze/message-http-adapter) adapter | **Outdated adapter, waiting for stabilization** 1. Source: [In `sroze/message-http-adapter`](https://github.com/sroze/message-http-adapter) <br/>2. Demo: [In `sroze/symfony-demo:message-component-demo-with-http-adapter`](sroze/symfony-demo@message-component-demo...sroze:message-component-demo-with-http-adapter) | Web profiler integration | _In the pull-request_ # Important points 1. **Tests are not in the PR as they were written in PhpSpec & Behat.** If we decide to go forward with this approach, I'll translate them to PHPUnit. 2. The aim is not to solve all the message/queuing problems but provide a good, simple and extensible message bus for developers. 3. The communication with the actual AMQP/API brokers is down to the adapters for now. Not sure if we need to ship some by default or not 🤔 I guess that this would replace #23842 & #23315. # Changes from the proposals Based on the comments, a few changes have been made from the proposal. 1. `MessageProducer`s have been renamed to `MessageSender`s 2. `MessageConsumer`s have been renamed to `MessageReceiver`s Commits ------- c9cfda990b [Messenger] Add a new Messenger component
This PR was squashed before being merged into the 4.1-dev branch (closes #24411). Discussion ---------- [Messenger] Add a new Messenger component | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #24326 | License | MIT | Doc PR | symfony/symfony-docs#9437 As discussed in #24326. This PR is to help going forward with the discussions of having a Message component. # Resources | What | Where | --- | --- | Documentation | [In the PR](https://github.com/sroze/symfony/blob/add-message-component/src/Symfony/Component/Message/README.md) | Demo | [In `sroze/symfony-demo:message-component-demo`](https://github.com/sroze/symfony-demo/compare/message-component-demo) | [php-enqueue](https://github.com/php-enqueue/enqueue-dev) adapter | 1. Source: [In `sroze/enqueue-bridge`](https://github.com/sroze/enqueue-bridge) _(to be moved as `symfony/enqueue-bridge` I guess)_<br/>2. Demo: [In `sroze/symfony-demo:message-component-demo-with-enqueue`](sroze/symfony-demo@message-component-demo...sroze:message-component-demo-with-enqueue) | [Swarrot](https://github.com/swarrot/swarrot) adapter | **Outdated adapter, waiting for stabilization** 1. Source: [In `sroze/swarrot-bridge`](https://github.com/sroze/swarrot-bridge) _(to be moved as `symfony/swarrot-bridge` I guess)_<br/>2. Demo: [In `sroze/symfony-demo:message-component-demo-with-swarrot`](sroze/symfony-demo@message-component-demo...sroze:message-component-demo-with-swarrot) | [HTTP](https://github.com/sroze/message-http-adapter) adapter | **Outdated adapter, waiting for stabilization** 1. Source: [In `sroze/message-http-adapter`](https://github.com/sroze/message-http-adapter) <br/>2. Demo: [In `sroze/symfony-demo:message-component-demo-with-http-adapter`](sroze/symfony-demo@message-component-demo...sroze:message-component-demo-with-http-adapter) | Web profiler integration | _In the pull-request_ # Important points 1. **Tests are not in the PR as they were written in PhpSpec & Behat.** If we decide to go forward with this approach, I'll translate them to PHPUnit. 2. The aim is not to solve all the message/queuing problems but provide a good, simple and extensible message bus for developers. 3. The communication with the actual AMQP/API brokers is down to the adapters for now. Not sure if we need to ship some by default or not 🤔 I guess that this would replace #23842 & #23315. # Changes from the proposals Based on the comments, a few changes have been made from the proposal. 1. `MessageProducer`s have been renamed to `MessageSender`s 2. `MessageConsumer`s have been renamed to `MessageReceiver`s Commits ------- c9cfda9 [Messenger] Add a new Messenger component
|
Should be updated as the component is now named Messenger. |
|
Yep. I'll go through the PR and re-phrase a bunch of things this weekend. |
minor doc fixes for the Message component
components/message.rst
Outdated
| ===================== | ||
|
|
||
| The Message component helps application to send and receive messages | ||
| to/from other applications or via |
There was a problem hiding this comment.
This phrase looks unfinished. Also, it's not a very descriptive description. Should we mention at least "message bus" or some key concept so the readers know undoubtely what problem does this component solve? Thanks!
components/message.rst
Outdated
|
|
||
| $ composer require symfony/message | ||
|
|
||
| Alternatively, you can clone the `<https://github.com/symfony/message>`_ repository. |
There was a problem hiding this comment.
This should be https://github.com/symfony/messenger.
components/message.rst
Outdated
|
|
||
| .. code-block:: terminal | ||
|
|
||
| $ composer require symfony/message |
There was a problem hiding this comment.
This should be symfony/messenger conform the composer.json.
components/message.rst
Outdated
| libraries for now. You can use one of the following adapters: | ||
|
|
||
| #. `PHP Enqueue bridge`_ to use one of their 10+ compatible queues such as | ||
| RabbitMq, Amazon SQS or Google Pub/Sub. |
components/message.rst
Outdated
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| To allow us to receive and send messages on the same bus and prevent a loop, the | ||
| message bus is equipped with the ``WrapIntoReceivedMessage`` received. It will |
There was a problem hiding this comment.
I'm having a hard time parsing this sentence, especially the last word 😕 . Either it should be a noun, or it should be "the received/obtained WrapIntoReceivedMessage object"
components/message.rst
Outdated
| A consumer is responsible for receiving messages from a source and dispatching | ||
| them to the application. | ||
|
|
||
| Let's say you already proceed some "orders" on your application using a |
components/message.rst
Outdated
| orders. | ||
|
|
||
| You will read this CSV file and dispatch a ``NewOrder`` message. All you need to | ||
| do is your custom CSV consumer and Symfony will do the rest. |
There was a problem hiding this comment.
"to do" => "to do is create your…" or "to write is your…"
components/message.rst
Outdated
|
|
||
| use App\Message\MyMessage; | ||
|
|
||
| $result = $this->get('message_bus')->handle(new MyMessage(/* ... */)); |
There was a problem hiding this comment.
Maybe use DI to get the message_bus service?
There was a problem hiding this comment.
Added an example of constructing it manually.
components/message.rst
Outdated
| .. code-block:: xml | ||
|
|
||
| <service id="App\Handler\MyMessageHandler"> | ||
| <tag name="message_handler" /> |
There was a problem hiding this comment.
should be message.handler according to message.receiver here: https://github.com/symfony/symfony-docs/pull/9437/files#diff-f4526c4dad3a0bd7e76fd35201a182f2R276
components/message.rst
Outdated
| } | ||
| } | ||
|
|
||
| .. code-block:: xml |
There was a problem hiding this comment.
you should add yaml config format, too
There was a problem hiding this comment.
This has to be moved within the FrameworkBundle's documentation actually.
components/message.rst
Outdated
| .. code-block:: yaml | ||
|
|
||
| framework: | ||
| message: |
components/message.rst
Outdated
| Asynchronous messages | ||
| ~~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| Using the Message Component is useful to decouple your application but it also |
There was a problem hiding this comment.
Using the Messenger Component
components/message.rst
Outdated
| Concepts | ||
| -------- | ||
|
|
||
| .. image:: /_images/components/message/overview.png |
There was a problem hiding this comment.
image:: /_images/components/messenger/overview.png
components/message.rst
Outdated
| .. code-block:: yaml | ||
|
|
||
| framework: | ||
| message: |
components/message.rst
Outdated
| .. code-block:: yaml | ||
|
|
||
| framework: | ||
| message: |
components/message.rst
Outdated
| .. note:: | ||
|
|
||
| If the message cannot be guessed from the handler's type-hint, use the | ||
| ``handles`` attribute on the tag. |
There was a problem hiding this comment.
I think best would be an example. Also mention that the guessing is done on the _invoke method argument
components/message.rst
Outdated
| arguments: | ||
| - "@serializer" | ||
| - "%new_orders_csv_file_path%" | ||
|
|
There was a problem hiding this comment.
please remove blank line here
|
Updated based on feedbacks, split the two documentations (i.e. as a "topic" and as a "component") and added more details. And Travis is green 🎉. Can I have the honor of another round of reviews? |
|
|
||
| .. code-block:: xml | ||
|
|
||
| <service id="App\MessageHandler\MyMessageHandler"> |
There was a problem hiding this comment.
To be consistent with other parts of Symfony, could we define an interface for Message Handlers so they can be autoconfigured?
There was a problem hiding this comment.
This is proposed in the following PR: symfony/symfony#26685. Though, it's controversial :)
messenger.rst
Outdated
| { | ||
| public function indexAction(MessageBusInterface $bus) | ||
| { | ||
| $bus->dispatch(new MyMessage()); |
There was a problem hiding this comment.
Could we use a more realistic example? Which is the simplest possible example where you can see the utility of messages and message bus? Also, can I store data inside a message class?
messenger.rst
Outdated
| framework: | ||
| messenger: | ||
| adapters: | ||
| default: "%env(MESSENGER_DSN)%" |
There was a problem hiding this comment.
Here the env var is called MESSENGER_DSN but below is AMQP_DSN
messenger.rst
Outdated
| This is enough to allow you to route your message to the :code:`messenger.default_adapter` | ||
| adapter. This will also configure the following for you: | ||
|
|
||
| 1. A :code:`messenger.default_sender` sender to be used when routing messages |
There was a problem hiding this comment.
This syntax:
:code:`...`
should be transformed to this:
``...``
in the whole article. Thanks!
messenger.rst
Outdated
| routing: | ||
| 'My\Message\Message': messenger.default_sender # Or another sender service name | ||
|
|
||
| Such configuration would only route the ``MessageAboutDoingOperationalWork`` |
There was a problem hiding this comment.
This paragraph mentions MessageAboutDoingOperationalWork ... but that's not used in the previous config example but in the next one.
components/messenger.rst
Outdated
| The bus is used to dispatch messages. The behaviour of the bus is in its ordered | ||
| middleware stack. The component comes with a set of middlewares that you can use. | ||
|
|
||
| When using the message bus with Symfony's FrameworkBundle, the following middlewares |
There was a problem hiding this comment.
middleware is uncountable in English, so no plural for it :)
messenger.rst
Outdated
| } | ||
| } | ||
|
|
||
| The :code:`YourAdaper` class need to implements the :code:`AdapterInterface`. It |
There was a problem hiding this comment.
I think here implements should be without s
messenger.rst
Outdated
|
|
||
| Instead of calling a handler, you have the option to route your message(s) to a | ||
| sender. Part of an adapter, it is responsible of sending your message somewhere. | ||
| You can configuration which message is routed to which sender with the following |
|
Ready for another round of reviews 👍 |
| The Messenger Component | ||
| ======================= | ||
|
|
||
| The Messenger component helps applications send and receive messages to/from other applications or via message queues. |
There was a problem hiding this comment.
- The Messenger component helps applications send and receive messages to/from other applications or via message queues.
+ The Messenger component helps applications send messages to and receive messages from other applications and via message queues.
components/messenger.rst
Outdated
| .. image:: /_images/components/messenger/overview.png | ||
|
|
||
| **Sender**: | ||
| Responsible for serializing and sending the message to _something_. This |
There was a problem hiding this comment.
- Responsible for serializing and sending the message to _something_. This
+ Responsible for serializing and sending messages to _something_. This
components/messenger.rst
Outdated
| something can be a message broker or a third party API for example. | ||
|
|
||
| **Receiver**: | ||
| Responsible for deserializing and forwarding the messages to handler(s). This |
There was a problem hiding this comment.
- Responsible for deserializing and forwarding the messages to handler(s). This
+ Responsible for deserializing and forwarding messages to handler(s). This
components/messenger.rst
Outdated
|
|
||
| **Handler**: | ||
| Given a received message, contains the user business logic related to the | ||
| message. In practice, that is just a PHP callable. |
There was a problem hiding this comment.
How about:-
Responsible for handling messages using the business logic applicable to the messages.
The part about PHP callable is confusing, explained better in the Handlers section, below and I think it should be omitted here.
components/messenger.rst
Outdated
|
|
||
| .. note: | ||
|
|
||
| Every middleware need to implement the ``MiddlewareInterface`` interface. |
| Handlers | ||
| -------- | ||
|
|
||
| Once dispatched to the bus, messages will be handled by a "message handler". A |
There was a problem hiding this comment.
"dispatched" is confusing here: according to the Bus section, the bus is responsible for dispatching messages; and the method used to get a message on to the bus is handle().
components/messenger.rst
Outdated
| Once dispatched to the bus, messages will be handled by a "message handler". A | ||
| message handler is a PHP callable (i.e. a function or an instance of a class) | ||
| that will do the required processing for your message. It _might_ return a | ||
| result:: |
There was a problem hiding this comment.
It might return a result
What happens if it does or does not return a result? Does the following example code illustrate something about this statement?
components/messenger.rst
Outdated
| -------- | ||
|
|
||
| The communication with queuing system or third parties is delegated to | ||
| libraries for now. |
There was a problem hiding this comment.
It isn't at all clear what this means or what are the implications for someone who intends to communicate with a queuing system or third party. Also system -> systems. And drop "for now" unless you want to say something about what will happen in the future.
components/messenger.rst
Outdated
| } | ||
| } | ||
|
|
||
| Same bus received and sender |
| } | ||
| } | ||
|
|
||
| Register your factory |
components/messenger.rst
Outdated
| $this->filePath = $filePath; | ||
| } | ||
|
|
||
| public function receive() : \Generator |
There was a problem hiding this comment.
iterable according to the interface?
boite
left a comment
There was a problem hiding this comment.
Good docs! Have managed to follow some and use the message bus and a message handler. :)
|
|
||
| use Symfony\Bundle\FrameworkBundle\Controller\Controller; | ||
| use Symfony\Component\Messenger\MessageBusInterface; | ||
|
|
There was a problem hiding this comment.
Please add something like use App\Message\SendNotification; to make clear that SendNotification is not provided by the messenger component.
| Using the Messenger Service | ||
| --------------------------- | ||
|
|
||
| Once enabled, the ``message_bus`` service can be injected in any service where |
There was a problem hiding this comment.
Will the following be enough to enable it?
# config/packages/framework.yml
framework:
messenger: ~And what exactly is being enabled here - is it the message_bus service (as the sentence seems to indicate) or is it the Messenger Component?
messenger.rst
Outdated
| ------- | ||
|
|
||
| Instead of calling a handler, you have the option to route your message(s) to a | ||
| sender. Part of an adapter, it is responsible of sending your message somewhere. |
| 'My\Message\Message': messenger.default_sender # Or another sender service name | ||
|
|
||
| Such configuration would only route the ``My\Message\Message`` message to be | ||
| asynchronous, the rest of the messages would still be directly handled. |
There was a problem hiding this comment.
Instead of two sentences, one before the config example and one after, how about just one:-
"The following configuration shows how you can route a class of messages to a sender, leaving other classes of messages to be passed to their respective handlers."
There was a problem hiding this comment.
Also, routing to messenger.default_sender seems to be wrong:-
In CheckExceptionOnInvalidReferenceBehaviorPass.php line 32:
[Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException]
The service "messenger.asynchronous.middleware.send_message_to_producer" ha
s a dependency on a non-existent service "messenger.default_sender".
It should be messenger.sender.default.
There was a problem hiding this comment.
It's less clear with a single example IMHO. I've updated the sender configuration 👍
messenger.rst
Outdated
| messenger: | ||
| routing: | ||
| 'My\Message\MessageAboutDoingOperationalWork': messenger.operations_sender | ||
| '*': messenger.default_sender |
There was a problem hiding this comment.
"You can route all classes of message to a sender using an asterisk instead of a class name:"
There was a problem hiding this comment.
Yep, nice call. Updated 👍
messenger.rst
Outdated
| Registering your middleware | ||
| --------------------------- | ||
|
|
||
| The message bus is based on a set of middleware. If you are un-familiar with the concept, |
messenger.rst
Outdated
|
|
||
| .. code-block:: xml | ||
|
|
||
| <service id="Your\Own\Middleware"> |
messenger.rst
Outdated
| Your own Adapters | ||
| ----------------- | ||
|
|
||
| Learn how to build your own adapters within the Component's documentation. Once |
There was a problem hiding this comment.
Learn how to build your own adapters within the Component's documentation.
It is unclear what is meant by this!
messenger.rst
Outdated
|
|
||
| Learn how to build your own adapters within the Component's documentation. Once | ||
| you have built your classes, you can register your adapter factory to be able to | ||
| use it via a DSN in the Symfony application. |
There was a problem hiding this comment.
In the "Use your adapter" section :)
messenger.rst
Outdated
| } | ||
|
|
||
| The ``YourAdaper`` class need to implement the ``AdapterInterface``. It | ||
| will like the following example:: |
There was a problem hiding this comment.
need -> needs
or
need to -> must
and
It will be like
or
It will look like
|
|
||
| **Sender**: | ||
| Responsible for serializing and sending the message to _something_. This | ||
| something can be a message broker or a third party API for example. |
There was a problem hiding this comment.
a messager handler, broker or a third-party API.
Reasons:
- The current phrasing kinda implies the component is very queue oriented. It's not wrong but it's not limited to this use case
- Using it with a message handler is a case common enough to be mentioned IMO
- I'm not sure all the people are familiar with queues and its related vocabulary so putting
message handlerwhich is likely to be more commonly known will make it more accessible
| -------- | ||
|
|
||
| Once dispatched to the bus, messages will be handled by a "message handler". A | ||
| message handler is a PHP callable (i.e. a function or an instance of a class) |
There was a problem hiding this comment.
we could add a link to the official doc here:
- callable: https://secure.php.net/manual/en/language.types.callable.php
- anonymous function: https://secure.php.net/manual/en/functions.anonymous.php
- an invokable class: https://secure.php.net/manual/en/language.oop5.magic.php#object.invoke
This PR was merged into the 4.1-dev branch. Discussion ---------- [Messenger] Rename the middleware tag | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | ø | License | MIT | Doc PR | symfony/symfony-docs#9437 After a using it for a bit of time, it's weird to have the `messenger.message_handler` tag while using the `message_bus_middleware` tag for the middlewares. I propose to rename the tag from `message_bus_middleware` to `messenger.bus_middleware` to keep some consistency. Commits ------- dd18445 Rename the middleware tag from `message_bus_middleware` to `messenger.bus_middleware`
messenger.rst
Outdated
| adapter. This will also configure the following for you: | ||
|
|
||
| 1. A ``messenger.default_sender`` sender to be used when routing messages | ||
| 2. A ``messenger.default_receiver`` receiver to be used when consuming messages. |
There was a problem hiding this comment.
These should be messenger.sender.default and messenger.receiver.default (there are numerous occurrences that need to be changed).
|
It's ready to be merged. Tweaks can follow in other PRs I suppose. |
messenger.rst
Outdated
| 'My\Message\MessageAboutDoingOperationalWork': another_adapter | ||
| '*': amqp | ||
|
|
||
| A class of message can also be routed to a multiple senders by specifying a list: |
There was a problem hiding this comment.
- A class of message can also be routed to a multiple senders by specifying a list:
+ A class of message can also be routed to multiple senders by specifying a list:|
@boite thank you very much for all your reviews, much appreciated! I've updated the wording of the sentence you highlighted in your last review. |
|
Well done @sroze; this all looks good. |
|
Let's merge this because, otherwise, this would be one of those eternal pull requests that never get merged. We can improve contents later as needed. Thanks Samuel for your contribution and thanks to the community for the reviews! |
…guiluz, wiese) This PR was merged into the master branch. Discussion ---------- Symfony Messenger component documentation This pull-request adds some documentation for the Messenger component. As it is, it's extracted from the README built incrementally in the code pull-request. I'm sure there will be lots to change when the implementation is merged :) Commits ------- c5306b8 Minor wording change 32403ea Update the documentation to reflect the latest changes 3fb973c Update based on comments 509e149 Add a documentation about middlewares and update based on reviews fb88abc Add Messenger in the topics a15752b Fix unresolved reference 25c0b6e It helps multiple applications Please enter the commit message for your changes. Lines starting bcfae23 Finish the documentation about the custom adapter 2493c90 Update typos and missing reference 31a56ee Uses `::` to display as code blocks 5c828e4 Update the documentation a bit, and add more FrameworkBundle documentation 88ba8fe Merge pull request #1 from wiese/patch-3 b26de80 minor doc fixes for the Message component b40bc71 Fixed the RST syntax issues 585491d Move the documentation from the main PR to RST format.
This pull-request adds some documentation for the Messenger component. As it is, it's extracted from the README built incrementally in the code pull-request.
I'm sure there will be lots to change when the implementation is merged :)