-
-
Notifications
You must be signed in to change notification settings - Fork 5.2k
[Messenger] Add the Envelope in the documentation #9757
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
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -95,6 +95,63 @@ that will do the required processing for your message:: | |
} | ||
} | ||
|
||
Adding Metadata to Messages (Envelopes) | ||
--------------------------------------- | ||
|
||
If you need to add metadata or some configuration to a message, wrap it with the | ||
:class:`Symfony\\Component\\Messenger\\Envelope` class. For example, to set the | ||
serialization groups used when the message goes through the transport layer, use | ||
the ``SerializerConfiguration`` envelope:: | ||
|
||
use Symfony\Component\Messenger\Envelope; | ||
use Symfony\Component\Messenger\Transport\Serialization\SerializerConfiguration; | ||
|
||
$bus->dispatch( | ||
(new Envelope($message))->with(new SerializerConfiguration([ | ||
'groups' => ['my_serialization_groups'], | ||
])) | ||
); | ||
|
||
At the moment, the Symfony Messenger has the following built-in envelopes: | ||
|
||
1. :class:`Symfony\\Component\\Messenger\\Transport\\Serialization\\SerializerConfiguration`, | ||
to configure the serialization groups used by the transport. | ||
2. :class:`Symfony\\Component\\Messenger\\Middleware\\Configuration\\ValidationConfiguration`, | ||
to configure the validation groups used when the validation middleware is enabled. | ||
3. :class:`Symfony\\Component\\Messenger\\Asynchronous\\Transport\\ReceivedMessage`, | ||
an internal item that marks the message as received from a transport. | ||
|
||
Instead of dealing directly with the messages in the middleware you can receive the | ||
envelope by implementing the :class:`Symfony\\Component\\Messenger\\EnvelopeAwareInterface` | ||
marker, like this:: | ||
|
||
use Symfony\Component\Messenger\Asynchronous\Transport\ReceivedMessage; | ||
use Symfony\Component\Messenger\Middleware\MiddlewareInterface; | ||
use Symfony\Component\Messenger\EnvelopeAwareInterface; | ||
|
||
class MyOwnMiddleware implements MiddlewareInterface, EnvelopeAwareInterface | ||
{ | ||
public function handle($message, callable $next) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, maybe we can rename There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. Please rename this. |
||
{ | ||
// $message here is an `Envelope` object, because this middleware | ||
// implements the EnvelopeAwareInterface interface. | ||
|
||
if (null !== $message->get(ReceivedMessage::class)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this Also, suppose some similar code: if Some inline comments with some of these answers might be all we need :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, is it a real use-case to look need to know whether or not a message was just received? If you're using an async transport and you want to do something for a specific message type, is it important that you make sure this processing is done only when your message has been "received"? If so, why? And if so, how could I both perform my action only when the message is "received" AND only check the class of the original message (e.g. I need to do something when my There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There is mis interpretation here. The
That's not also, that's the only thing you can do :)
if (nul !== $message->get(ReceivedMessage::class) && $message->getMessage() instanceof YourOwnMessageClass) {
// Your logic...
} Might be clearer if we rename |
||
// Message just has been received... | ||
|
||
// You could for example add another item. | ||
$message = $message->with(new AnotherEnvelopeItem(/* ... */)); | ||
} | ||
|
||
return $next($message); | ||
} | ||
} | ||
|
||
The above example will forward the message to the next middleware with an additional | ||
envelope item if the message has just been received (i.e. has the `ReceivedMessage` item). | ||
You can create your own items by implementing the :class:`Symfony\\Component\\Messenger\\EnvelopeAwareInterface` | ||
interface. | ||
|
||
Transports | ||
---------- | ||
|
||
|
@@ -115,6 +172,7 @@ First, create your sender:: | |
|
||
use App\Message\ImportantAction; | ||
use Symfony\Component\Messenger\Transport\SenderInterface; | ||
use Symfony\Component\Messenger\Envelope; | ||
|
||
class ImportantActionToEmailSender implements SenderInterface | ||
{ | ||
|
@@ -127,10 +185,12 @@ First, create your sender:: | |
$this->toEmail = $toEmail; | ||
} | ||
|
||
public function send($message) | ||
public function send(Envelope $envelope) | ||
{ | ||
$message = $envelope->getMessage(); | ||
|
||
if (!$message instanceof ImportantAction) { | ||
throw new \InvalidArgumentException(sprintf('Producer only supports "%s" messages.', ImportantAction::class)); | ||
throw new \InvalidArgumentException(sprintf('This transport only supports "%s" messages.', ImportantAction::class)); | ||
} | ||
|
||
$this->mailer->send( | ||
|
@@ -165,6 +225,7 @@ First, create your receiver:: | |
use App\Message\NewOrder; | ||
use Symfony\Component\Messenger\Transport\ReceiverInterface; | ||
use Symfony\Component\Serializer\SerializerInterface; | ||
use Symfony\Component\Messenger\Envelope; | ||
|
||
class NewOrdersFromCsvFile implements ReceiverInterface | ||
{ | ||
|
@@ -182,7 +243,9 @@ First, create your receiver:: | |
$ordersFromCsv = $this->serializer->deserialize(file_get_contents($this->filePath), 'csv'); | ||
|
||
foreach ($ordersFromCsv as $orderFromCsv) { | ||
$handler(new NewOrder($orderFromCsv['id'], $orderFromCsv['account_id'], $orderFromCsv['amount'])); | ||
$order = new NewOrder($orderFromCsv['id'], $orderFromCsv['account_id'], $orderFromCsv['amount']); | ||
|
||
$handler(new Envelope($order)); | ||
} | ||
} | ||
|
||
|
@@ -196,10 +259,9 @@ Receiver and Sender on the same Bus | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
To allow sending and receiving messages on the same bus and prevent an infinite | ||
loop, the message bus is equipped with the ``WrapIntoReceivedMessage`` middleware. | ||
It will wrap the received messages into ``ReceivedMessage`` objects and the | ||
``SendMessageMiddleware`` middleware will know it should not route these | ||
messages again to a transport. | ||
loop, the message bus will add a :class:`Symfony\\Component\\Messenger\\Asynchronous\\Transport\\ReceivedMessage` | ||
envelope item to the message envelopes and the :class:`Symfony\\Component\\Messenger\\Asynchronous\\Middleware\\SendMessageMiddleware` | ||
middleware will know it should not route these messages again to a transport. | ||
|
||
.. _blog posts about command buses: https://matthiasnoback.nl/tags/command%20bus/ | ||
.. _SimpleBus project: http://simplebus.io |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could mention others built-in configurations available (just
ValidationConfiguration
for now) here or in another section.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just did 👍