8000 symfony-docs/messenger.rst at 4.3 · symfony/symfony-docs · GitHub
[go: up one dir, main page]

Skip to content
{"payload":{"allShortcutsEnabled":false,"fileTree":{"":{"items":[{"name":".github","path":".github","contentType":"directory"},{"name":".symfony","path":".symfony","contentType":"directory"},{"name":"_build","path":"_build","contentType":"directory"},{"name":"_images","path":"_images","contentType":"directory"},{"name":"_includes","path":"_includes","contentType":"directory"},{"name":"bundles","path":"bundles","contentType":"directory"},{"name":"components","path":"components","contentType":"directory"},{"name":"configuration","path":"configuration","contentType":"directory"},{"name":"console","path":"console","contentType":"directory"},{"name":"contributing","path":"contributing","contentType":"directory"},{"name":"controller","path":"controller","contentType":"directory"},{"name":"create_framework","path":"create_framework","contentType":"directory"},{"name":"deployment","path":"deployment","contentType":"directory"},{"name":"doctrine","path":"doctrine","contentType":"directory"},{"name":"event_dispatcher","path":"event_dispatcher","contentType":"directory"},{"name":"form","path":"form","contentType":"directory"},{"name":"frontend","path":"frontend","contentType":"directory"},{"name":"getting_started","path":"getting_started","contentType":"directory"},{"name":"http_cache","path":"http_cache","contentType":"directory"},{"name":"introduction","path":"introduction","contentType":"directory"},{"name":"logging","path":"logging","contentType":"directory"},{"name":"messenger","path":"messenger","contentType":"directory"},{"name":"profiler","path":"profiler","contentType":"directory"},{"name":"quick_tour","path":"quick_tour","contentType":"directory"},{"name":"reference","path":"reference","contentType":"directory"},{"name":"routing","path":"routing","contentType":"directory"},{"name":"security","path":"security","contentType":"directory"},{"name":"serializer","path":"serializer","contentType":"directory"},{"name":"service_container","path":"service_container","contentType":"directory"},{"name":"session","path":"session","contentType":"directory"},{"name":"setup","path":"setup","contentType":"directory"},{"name":"templating","path":"templating","contentType":"directory"},{"name":"testing","path":"testing","contentType":"directory"},{"name":"translation","path":"translation","contentType":"directory"},{"name":"validation","path":"validation","contentType":"directory"},{"name":"workflow","path":"workflow","contentType":"directory"},{"name":".doctor-rst.yaml","path":".doctor-rst.yaml","contentType":"file"},{"name":".editorconfig","path":".editorconfig","contentType":"file"},{"name":".gitignore","path":".gitignore","contentType":"file"},{"name":".symfony.cloud.yaml","path":".symfony.cloud.yaml","contentType":"file"},{"name":".travis.yml","path":".travis.yml","contentType":"file"},{"name":"CODE_OF_CONDUCT.md","path":"CODE_OF_CONDUCT.md","contentType":"file"},{"name":"Dockerfile","path":"Dockerfile","contentType":"file"},{"name":"LICENSE.md","path":"LICENSE.md","contentType":"file"},{"name":"README.markdown","path":"README.markdown","contentType":"file"},{"name":"best_practices.rst","path":"best_practices.rst","contentType":"file"},{"name":"bundles.rst","path":"bundles.rst","contentType":"file"},{"name":"cache.rst","path":"cache.rst","contentType":"file"},{"name":"configuration.rst","path":"configuration.rst","contentType":"file"},{"name":"console.rst","path":"console.rst","contentType":"file"},{"name":"controller.rst","path":"controller.rst","contentType":"file"},{"name":"deployment.rst","path":"deployment.rst","contentType":"file"},{"name":"doctrine.rst","path":"doctrine.rst","contentType":"file"},{"name":"email.rst","path":"email.rst","contentType":"file"},{"name":"event_dispatcher.rst","path":"event_dispatcher.rst","contentType":"file"},{"name":"forms.rst","path":"forms.rst","contentType":"file"},{"name":"frontend.rst","path":"frontend.rst","contentType":"file"},{"name":"http_cache.rst","path":"http_cache.rst","contentType":"file"},{"name":"index.rst","path":"index.rst","contentType":"file"},{"name":"logging.rst","path":"logging.rst","contentType":"file"},{"name":"mailer.rst","path":"mailer.rst","contentType":"file"},{"name":"mercure.rst","path":"mercure.rst","contentType":"file"},{"name":"messenger.rst","path":"messenger.rst","contentType":"file"},{"name":"migration.rst","path":"migration.rst","contentType":"file"},{"name":"page_creation.rst","path":"page_creation.rst","contentType":"file"},{"name":"performance.rst","path":"performance.rst","contentType":"file"},{"name":"profiler.rst","path":"profiler.rst","contentType":"file"},{"name":"routing.rst","path":"routing.rst","contentType":"file"},{"name":"security.rst","path":"security.rst","contentType":"file"},{"name":"serializer.rst","path":"serializer.rst","contentType":"file"},{"name":"service_container.rst","path":"service_container.rst","contentType":"file"},{"name":"session.rst","path":"session.rst","contentType":"file"},{"name":"setup.rst","path":"setup.rst","contentType":"file"},{"name":"templates.rst","path":"templates.rst","contentType":"file"},{"name":"testing.rst","path":"testing.rst","contentType":"file"},{"name":"translation.rst","path":"translation.rst","contentType":"file"},{"name":"validation.rst","path":"validation.rst","contentType":"file"},{"name":"web_link.rst","path":"web_link.rst","contentType":"file"},{"name":"workflow.rst","path":"workflow.rst","contentType":"file"}],"totalCount":79}},"fileTreeProcessingTime":2.9952949999999996,"foldersToFetch":[],"incompleteFileTree":false,"repo":{"id":521583,"defaultBranch":"7.3","name":"symfony-docs","ownerLogin":"symfony","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2010-02-17T08:43:51.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/143937?v=4","public":true,"private":false,"isOrgOwned":true},"codeLineWrapEnabled":false,"symbolsExpanded":false,"treeExpanded":true,"refInfo":{"name":"4.3","listCacheKey":"v0:1740861846.0","canEdit":false,"refType":"branch","currentOid":"96723ac04ad7d73ed50f24d3f4a688c5a857934f"},"path":"messenger.rst","currentUser":null,"blob":{"rawLines":null,"stylingDirectives":null,"colorizedLines":null,"csv":null,"csvError":null,"dependabotInfo":{"showConfigurationBanner":false,"configFilePath":null,"networkDependabotPath":"/symfony/symfony-docs/network/updates","dismissConfigurationNoticePath":"/settings/dismiss-notice/dependabot_configuration_notice","configurationNoticeDismissed":null},"displayName":"messenger.rst","displayUrl":"https://github.com/symfony/symfony-docs/blob/4.3/messenger.rst?raw=true","headerInfo":{"blobSize":"53 KB","deleteTooltip":"You must be signed in to make or propose changes","editTooltip":"You must be signed in to make or propose changes","ghDesktopPath":"https://desktop.github.com","isGitLfs":false,"onBranch":true,"shortPath":"3d2ef6e","siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2Fsymfony%2Fsymfony-docs%2Fblob%2F4.3%2Fmessenger.rst","isCSV":false,"isRichtext":true,"toc":[{"level":2,"text":"Messenger: Sync \u0026 Queued Message Handling","anchor":"messenger-sync--queued-message-handling","htmlText":"Messenger: Sync \u0026amp; Queued Message Handling"},{"level":3,"text":"Installation","anchor":"installation","htmlText":"Installation"},{"level":3,"text":"Creating a Message \u0026 Handler","anchor":"creating-a-message--handler","htmlText":"Creating a Message \u0026amp; Handler"},{"level":3,"text":"Dispatching the Message","anchor":"dispatching-the-message","htmlText":"Dispatching the Message"},{"level":3,"text":"Transports: Async/Queued Messages","anchor":"transports-asyncqueued-messages","htmlText":"Transports: Async/Queued Messages"},{"level":4,"text":"Routing Messages to a Transport","anchor":"routing-messages-to-a-transport","htmlText":"Routing Messages to a Transport"},{"level":4,"text":"Doctrine Entities in Messages","anchor":"doctrine-entities-in-messages","htmlText":"Doctrine Entities in Messages"},{"level":4,"text":"Handling Messages Synchronously","anchor":"handling-messages-synchronously","htmlText":"Handling Messages Synchronously"},{"level":4,"text":"Creating your Own Transport","anchor":"creating-your-own-transport","htmlText":"Creating your Own Transport"},{"level":3,"text":"Consuming Messages (Running the Worker)","anchor":"consuming-messages-running-the-worker","htmlText":"Consuming Messages (Running the Worker)"},{"level":4,"text":"Deploying to Production","anchor":"deploying-to-production","htmlText":"Deploying to Production"},{"level":4,"text":"Prioritized Transports","anchor":"prioritized-transports","htmlText":"Prioritized Transports"},{"level":4,"text":"Supervisor Configuration","anchor":"supervisor-configuration","htmlText":"Supervisor Configuration"},{"level":3,"text":"Retries \u0026 Failures","anchor":"retries--failures","htmlText":"Retries \u0026amp; Failures"},{"level":4,"text":"Avoiding Retrying","anchor":"avoiding-retrying","htmlText":"Avoiding Retrying"},{"level":4,"text":"Saving \u0026 Retrying Failed Messages","anchor":"saving--retrying-failed-messages","htmlText":"Saving \u0026amp; Retrying Failed Messages"},{"level":3,"text":"Transport Configuration","anchor":"transport-configuration","htmlText":"Transport Configuration"},{"level":4,"text":"AMQP Transport","anchor":"amqp-transport","htmlText":"AMQP Transport"},{"level":4,"text":"Doctrine Transport","anchor":"doctrine-transport","htmlText":"Doctrine Transport"},{"level":4,"text":"Redis Transport","anchor":"redis-transport","htmlText":"Redis Transport"},{"level":4,"text":"In Memory Transport","anchor":"in-memory-transport","htmlText":"In Memory Transport"},{"level":4,"text":"Serializing Messages","anchor":"serializing-messages","htmlText":"Serializing Messages"},{"level":3,"text":"Customizing Handlers","anchor":"customizing-handlers","htmlText":"Customizing Handlers"},{"level":4,"text":"Manually Configuring Handlers","anchor":"manually-configuring-handlers","htmlText":"Manually Configuring Handlers"},{"level":4,"text":"Handler Subscriber \u0026 Options","anchor":"handler-subscriber--options","htmlText":"Handler Subscriber \u0026amp; Options"},{"level":4,"text":"Binding Handlers to Different Transports","anchor":"binding-handlers-to-different-transports","htmlText":"Binding Handlers to Different Transports"},{"level":3,"text":"Extending Messenger","anchor":"extending-messenger","htmlText":"Extending Messenger"},{"level":4,"text":"Envelopes \u0026 Stamps","anchor":"envelopes--stamps","htmlText":"Envelopes \u0026amp; Stamps"},{"level":4,"text":"Middleware","anchor":"middleware","htmlText":"Middleware"},{"level":4,"text":"Middleware for Doctrine","anchor":"middleware-for-doctrine","htmlText":"Middleware for Doctrine"},{"level":4,"text":"Messenger Events","anchor":"messenger-events","htmlText":"Messenger Events"},{"level":3,"text":"Multiple Buses, Command \u0026 Event Buses","anchor":"multiple-buses-command--event-buses","htmlText":"Multiple Buses, Command \u0026amp; Event Buses"},{"level":3,"text":"Learn more","anchor":"learn-more","htmlText":"Learn more"}],"lineInfo":{"truncatedLoc":"1487","truncatedSloc":"1133"},"mode":"file"},"image":false,"isCodeownersFile":null,"isPlain":false,"isValidLegacyIssueTemplate":false,"issueTemplate":null,"discussionTemplate":null,"language":"reStructuredText","languageID":419,"large":false,"planSupportInfo":{"repoIsFork":null,"repoOwnedByCurrentUser":null,"requestFullPath":"/symfony/symfony-docs/blob/4.3/messenger.rst","showFreeOrgGatedFeatureMessage":null,"showPlanSupportBanner":null,"upgradeDataAttributes":null,"upgradePath":null},"publishBannersInfo":{"dismissActionNoticePath":"/settings/dismiss-notice/publish_action_from_dockerfile","releasePath":"/symfony/symfony-docs/releases/new?marketplace=true","showPublishActionBanner":false},"rawBlobUrl":"https://github.com/symfony/symfony-docs/raw/refs/heads/4.3/messenger.rst","renderImageOrRaw":false,"richText":"\u003carticle class=\"markdown-body entry-content container-lg\" itemprop=\"text\"\u003e\u003cpre\u003e.. index::\n single: Messenger\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-messenger-sync-queued-message-handling\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eMessenger: Sync \u0026amp; Queued Message Handling\u003c/h2\u003e\u003ca id=\"user-content-messenger-sync--queued-message-handling\" class=\"anchor\" aria-label=\"Permalink: Messenger: Sync \u0026amp; Queued Message Handling\" href=\"#messenger-sync--queued-message-handling\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eMessenger provides a message bus with the ability to send messages and then\nhandle them immediately in your application or send them through transports\n(e.g. queues) to be handled later. To learn more deeply about it, read the\n\u003ca href=\"#id1\"\u003e\u003cspan id=\"user-content-id2\"\u003e:doc:`Messenger component docs \u0026lt;/components/messenger\u0026gt;`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003ca name=\"user-content-installation\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eInstallation\u003c/h3\u003e\u003ca id=\"user-content-installation\" class=\"anchor\" aria-label=\"Permalink: Installation\" href=\"#installation\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIn applications using \u003ca href=\"#id3\"\u003e\u003cspan id=\"user-content-id4\"\u003e:ref:`Symfony Flex \u0026lt;symfony-flex\u0026gt;`\u003c/span\u003e\u003c/a\u003e, run this command to\ninstall messenger:\u003c/p\u003e\n\u003cpre lang=\"terminal\"\u003e$ composer require messenger\n\u003c/pre\u003e\n\u003ca name=\"user-content-creating-a-message-handler\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCreating a Message \u0026amp; Handler\u003c/h3\u003e\u003ca id=\"user-content-creating-a-message--handler\" class=\"anchor\" aria-label=\"Permalink: Creating a Message \u0026amp; Handler\" href=\"#creating-a-message--handler\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eMessenger centers around two different classes that you'll create: (1) a message\nclass that holds data and (2) a handler(s) class that will be called when that\nmessage is dispatched. The handler class will read the message class and perform\nsome task.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThere are no specific requirements for a message class, except that it can be\nserialized:\u003c/p\u003e\n\u003cpre\u003e// src/Message/SmsNotification.php\nnamespace App\\Message;\n\nclass SmsNotification\n{\n private $content;\n\n public function __construct(string $content)\n {\n $this-\u0026gt;content = $content;\n }\n\n public function getContent(): string\n {\n return $this-\u0026gt;content;\n }\n}\n\u003c/pre\u003e\n\u003cp id=\"user-content-messenger-handler\" dir=\"auto\"\u003eA message handler is a PHP callable, the recommended way to create it is to\ncreate a class that implements \u003ca href=\"#id5\"\u003e\u003cspan id=\"user-content-id6\"\u003e:class:`Symfony\\\\Component\\\\Messenger\\\\Handler\\\\MessageHandlerInterface`\u003c/span\u003e\u003c/a\u003e\nand has an \u003ccode\u003e__invoke()\u003c/code\u003e method that's type-hinted with the message class (or a\nmessage interface):\u003c/p\u003e\n\u003cpre\u003e// src/MessageHandler/SmsNotificationHandler.php\nnamespace App\\MessageHandler;\n\nuse App\\Message\\SmsNotification;\nuse Symfony\\Component\\Messenger\\Handler\\MessageHandlerInterface;\n\nclass SmsNotificationHandler implements MessageHandlerInterface\n{\n public function __invoke(SmsNotification $message)\n {\n // ... do some work - like sending an SMS message!\n }\n}\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThanks to \u003ca href=\"#id7\"\u003e\u003cspan id=\"user-content-id8\"\u003e:ref:`autoconfiguration \u0026lt;services-autoconfigure\u0026gt;`\u003c/span\u003e\u003c/a\u003e and the \u003ccode\u003eSmsNotification\u003c/code\u003e\ntype-hint, Symfony knows that this handler should be called when an \u003ccode\u003eSmsNotification\u003c/code\u003e\nmessage is dispatched. Most of the time, this is all you need to do. But you can\nalso \u003ca href=\"#id9\"\u003e\u003cspan id=\"user-content-id10\"\u003e:ref:`manually configure message handlers \u0026lt;messenger-handler-config\u0026gt;`\u003c/span\u003e\u003c/a\u003e. To\nsee all the configured handlers, run:\u003c/p\u003e\n\u003cpre lang=\"terminal\"\u003e$ php bin/console debug:messenger\n\u003c/pre\u003e\n\u003ca name=\"user-content-dispatching-the-message\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDispatching the Message\u003c/h3\u003e\u003ca id=\"user-content-dispatching-the-message\" class=\"anchor\" aria-label=\"Permalink: Dispatching the Message\" href=\"#dispatching-the-message\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eYou're ready! To dispatch the message (and call the handler), inject the\n\u003ccode\u003emessage_bus\u003c/code\u003e service (via the \u003ccode\u003eMessageBusInterface\u003c/code\u003e), like in a controller:\u003c/p\u003e\n\u003cpre\u003e// src/Controller/DefaultController.php\nnamespace App\\Controller;\n\nuse App\\Message\\SmsNotification;\nuse Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController;\nuse Symfony\\Component\\Messenger\\MessageBusInterface;\n\nclass DefaultController extends AbstractController\n{\n public function index(MessageBusInterface $bus)\n {\n // will cause the SmsNotificationHandler to be called\n $bus-\u0026gt;dispatch(new SmsNotification('Look! I created a message!'));\n\n // or use the shortcut\n $this-\u0026gt;dispatchMessage(new SmsNotification('Look! I created a message!'));\n\n // ...\n }\n}\n\u003c/pre\u003e\n\u003ca name=\"user-content-transports-async-queued-messages\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTransports: Async/Queued Messages\u003c/h3\u003e\u003ca id=\"user-content-transports-asyncqueued-messages\" class=\"anchor\" aria-label=\"Permalink: Transports: Async/Queued Messages\" href=\"#transports-asyncqueued-messages\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eBy default, messages are handled as soon as they are dispatched. If you want\nto handle a message asynchronously, you can configure a transport. A transport\nis capable of sending messages (e.g. to a queueing system) and then\n\u003ca href=\"#id11\"\u003e\u003cspan id=\"user-content-id12\"\u003e:ref:`receiving them via a worker \u0026lt;messenger-worker\u0026gt;`\u003c/span\u003e\u003c/a\u003e. Messenger supports\n\u003ca href=\"#id13\"\u003e\u003cspan id=\"user-content-id14\"\u003e:ref:`multiple transports \u0026lt;messenger-transports-config\u0026gt;`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eNote\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIf you want to use a transport that's not supported, check out the\n\u003ca href=\"https://github.com/sroze/messenger-enqueue-transport\"\u003eEnqueue's transport\u003c/a\u003e, which supports things like Kafka, Amazon SQS and\nGoogle Pub/Sub.\u003c/p\u003e\n\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eA transport is registered using a \"DSN\". Thanks to Messenger's Flex recipe, your\n\u003ccode\u003e.env\u003c/code\u003e file already has a few examples.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages\n# MESSENGER_TRANSPORT_DSN=doctrine://default\n# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e MESSENGER_TRANSPORT_DSN=doctrine://default\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eUncomment whichever transport you want (or set it in \u003ccode\u003e.env.local\u003c/code\u003e). See\n\u003ca href=\"#id15\"\u003e\u003cspan id=\"user-content-id16\"\u003e:ref:`messenger-transports-config`\u003c/span\u003e\u003c/a\u003e for more details.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eNext, in \u003ccode\u003econfig/packages/messenger.yaml\u003c/code\u003e, let's define a transport called \u003ccode\u003easync\u003c/code\u003e\nthat uses this configuration:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # config/packages/messenger.yaml\n framework:\n messenger:\n transports:\n async: \"%env(MESSENGER_TRANSPORT_DSN)%\"\n\n # or expanded to configure more options\n #async:\n # dsn: \"%env(MESSENGER_TRANSPORT_DSN)%\"\n # options: []\n\n .. code-block:: xml\n\n \u0026lt;!-- config/packages/messenger.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\" ?\u0026gt;\n \u0026lt;container xmlns=\"http://symfony.com/schema/dic/services\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:framework=\"http://symfony.com/schema/dic/symfony\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n https://symfony.com/schema/dic/services/services-1.0.xsd\n http://symfony.com/schema/dic/symfony\n https://symfony.com/schema/dic/symfony/symfony-1.0.xsd\"\u0026gt;\n\n \u0026lt;framework:config\u0026gt;\n \u0026lt;framework:messenger\u0026gt;\n \u0026lt;framework:transport name=\"async\"\u0026gt;%env(MESSENGER_TRANSPORT_DSN)%\u0026lt;/framework:transport\u0026gt;\n\n \u0026lt;!-- or expanded to configure more options --\u0026gt;\n \u0026lt;framework:transport name=\"async\"\n dsn=\"%env(MESSENGER_TRANSPORT_DSN)%\"\n \u0026gt;\n \u0026lt;option key=\"...\"\u0026gt;...\u0026lt;/option\u0026gt;\n \u0026lt;/framework:transport\u0026gt;\n \u0026lt;/framework:messenger\u0026gt;\n \u0026lt;/framework:config\u0026gt;\n \u0026lt;/container\u0026gt;\n\n .. code-block:: php\n\n // config/packages/messenger.php\n $container-\u0026gt;loadFromExtension('framework', [\n 'messenger' =\u0026gt; [\n 'transports' =\u0026gt; [\n 'async' =\u0026gt; '%env(MESSENGER_TRANSPORT_DSN)%',\n\n // or expanded to configure more options\n 'async' =\u0026gt; [\n 'dsn' =\u0026gt; '%env(MESSENGER_TRANSPORT_DSN)%',\n 'options' =\u0026gt; []\n ],\n ],\n ],\n ]);\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-routing-messages-to-a-transport\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eRouting Messages to a Transport\u003c/h4\u003e\u003ca id=\"user-content-routing-messages-to-a-transport\" class=\"anchor\" aria-label=\"Permalink: Routing Messages to a Transport\" href=\"#routing-messages-to-a-transport\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eNow that you have a transport configured, instead of handling a message immediately,\nyou can configure them to be sent to a transport:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # config/packages/messenger.yaml\n framework:\n messenger:\n transports:\n async: \"%env(MESSENGER_TRANSPORT_DSN)%\"\n\n routing:\n # async is whatever name you gave your transport above\n 'App\\Message\\SmsNotification': async\n\n .. code-block:: xml\n\n \u0026lt;!-- config/packages/messenger.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\" ?\u0026gt;\n \u0026lt;container xmlns=\"http://symfony.com/schema/dic/services\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:framework=\"http://symfony.com/schema/dic/symfony\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n https://symfony.com/schema/dic/services/services-1.0.xsd\n http://symfony.com/schema/dic/symfony\n https://symfony.com/schema/dic/symfony/symfony-1.0.xsd\"\u0026gt;\n\n \u0026lt;framework:config\u0026gt;\n \u0026lt;framework:messenger\u0026gt;\n \u0026lt;framework:routing message-class=\"App\\Message\\SmsNotification\"\u0026gt;\n \u0026lt;!-- async is whatever name you gave your transport above --\u0026gt;\n \u0026lt;framework:sender service=\"async\"/\u0026gt;\n \u0026lt;/framework:routing\u0026gt;\n \u0026lt;/framework:messenger\u0026gt;\n \u0026lt;/framework:config\u0026gt;\n \u0026lt;/container\u0026gt;\n\n .. code-block:: php\n\n // config/packages/messenger.php\n $container-\u0026gt;loadFromExtension('framework', [\n 'messenger' =\u0026gt; [\n 'routing' =\u0026gt; [\n // async is whatever name you gave your transport above\n 'App\\Message\\SmsNotification' =\u0026gt; 'async',\n ],\n ],\n ]);\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThanks to this, the \u003ccode\u003eApp\\Message\\SmsNotification\u003c/code\u003e will be sent to the \u003ccode\u003easync\u003c/code\u003e\ntransport and its handler(s) will \u003cem\u003enot\u003c/em\u003e be called immediately. Any messages not\nmatched under \u003ccode\u003erouting\u003c/code\u003e will still be handled immediately.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eYou can also route classes by their parent class or interface. Or send messages\nto multiple transport:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # config/packages/messenger.yaml\n framework:\n messenger:\n routing:\n # route all messages that extend this example base class or interface\n 'App\\Message\\AbstractAsyncMessage': async\n 'App\\Message\\AsyncMessageInterface': async\n\n 'My\\Message\\ToBeSentToTwoSenders': [async, audit]\n\n .. code-block:: xml\n\n \u0026lt;!-- config/packages/messenger.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\" ?\u0026gt;\n \u0026lt;container xmlns=\"http://symfony.com/schema/dic/services\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:framework=\"http://symfony.com/schema/dic/symfony\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n https://symfony.com/schema/dic/services/services-1.0.xsd\n http://symfony.com/schema/dic/symfony\n https://symfony.com/schema/dic/symfony/symfony-1.0.xsd\"\u0026gt;\n\n \u0026lt;framework:config\u0026gt;\n \u0026lt;framework:messenger\u0026gt;\n \u0026lt;!-- route all messages that extend this example base class or interface --\u0026gt;\n \u0026lt;framework:routing message-class=\"App\\Message\\AbstractAsyncMessage\"\u0026gt;\n \u0026lt;framework:sender service=\"async\"/\u0026gt;\n 10000 \u0026lt;/framework:routing\u0026gt;\n \u0026lt;framework:routing message-class=\"App\\Message\\AsyncMessageInterface\"\u0026gt;\n \u0026lt;framework:sender service=\"async\"/\u0026gt;\n \u0026lt;/framework:routing\u0026gt;\n \u0026lt;framework:routing message-class=\"My\\Message\\ToBeSentToTwoSenders\"\u0026gt;\n \u0026lt;framework:sender service=\"async\"/\u0026gt;\n \u0026lt;framework:sender service=\"audit\"/\u0026gt;\n \u0026lt;/framework:routing\u0026gt;\n \u0026lt;/framework:messenger\u0026gt;\n \u0026lt;/framework:config\u0026gt;\n \u0026lt;/container\u0026gt;\n\n .. code-block:: php\n\n // config/packages/messenger.php\n $container-\u0026gt;loadFromExtension('framework', [\n 'messenger' =\u0026gt; [\n 'routing' =\u0026gt; [\n // route all messages that extend this example base class or interface\n 'App\\Message\\AbstractAsyncMessage' =\u0026gt; 'async',\n 'App\\Message\\AsyncMessageInterface' =\u0026gt; 'async',\n 'My\\Message\\ToBeSentToTwoSenders' =\u0026gt; ['async', 'audit'],\n ],\n ],\n ]);\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-doctrine-entities-in-messages\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDoctrine Entities in Messages\u003c/h4\u003e\u003ca id=\"user-content-doctrine-entities-in-messages\" class=\"anchor\" aria-label=\"Permalink: Doctrine Entities in Messages\" href=\"#doctrine-entities-in-messages\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIf you need to pass a Doctrine entity in a message, it's better to pass the entity's\nprimary key (or whatever relevant information the handler actually needs, like \u003ccode\u003eemail\u003c/code\u003e,\netc) instead of the object:\u003c/p\u003e\n\u003cpre\u003eclass NewUserWelcomeEmail\n{\n private $userId;\n\n public function __construct(int $userId)\n {\n $this-\u0026gt;userId = $userId;\n }\n\n public function getUserId(): int\n {\n return $this-\u0026gt;userId;\n }\n}\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThen, in your handler, you can query for a fresh object:\u003c/p\u003e\n\u003cpre\u003e// src/MessageHandler/NewUserWelcomeEmailHandler.php\nnamespace App\\MessageHandler;\n\nuse App\\Message\\NewUserWelcomeEmail;\nuse App\\Repository\\UserRepository;\nuse Symfony\\Component\\Messenger\\Handler\\MessageHandlerInterface;\n\nclass NewUserWelcomeEmailHandler implements MessageHandlerInterface\n{\n private $userRepository;\n\n public function __construct(UserRepository $userRepository)\n {\n $this-\u0026gt;userRepository = $userRepository;\n }\n\n public function __invoke(NewUserWelcomeEmail $welcomeEmail)\n {\n $user = $this-\u0026gt;userRepository-\u0026gt;find($welcomeEmail-\u0026gt;getUserId());\n\n // ... send an email!\n }\n}\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThis guarantees the entity contains fresh data.\u003c/p\u003e\n\u003ca name=\"user-content-handling-messages-synchronously\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eHandling Messages Synchronously\u003c/h4\u003e\u003ca id=\"user-content-handling-messages-synchronously\" class=\"anchor\" aria-label=\"Permalink: Handling Messages Synchronously\" href=\"#handling-messages-synchronously\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIf a message doesn't \u003ca href=\"#id17\"\u003e\u003cspan id=\"user-content-id18\"\u003e:ref:`match any routing rules \u0026lt;messenger-routing\u0026gt;`\u003c/span\u003e\u003c/a\u003e, it won't\nbe sent to any transport and will be handled immediately. In some cases (like\nwhen \u003ca href=\"#binding-handlers-to-different-transports\"\u003ebinding handlers to different transports\u003c/a\u003e),\nit's easier or more flexible to handle this explicitly: by creating a \u003ccode\u003esync\u003c/code\u003e\ntransport and \"sending\" messages there to be handled immediately:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # config/packages/messenger.yaml\n framework:\n messenger:\n transports:\n # ... other transports\n\n sync: 'sync://'\n\n routing:\n App\\Message\\SmsNotification: sync\n\n .. code-block:: xml\n\n \u0026lt;!-- config/packages/messenger.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\" ?\u0026gt;\n \u0026lt;container xmlns=\"http://symfony.com/schema/dic/services\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:framework=\"http://symfony.com/schema/dic/symfony\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n https://symfony.com/schema/dic/services/services-1.0.xsd\n http://symfony.com/schema/dic/symfony\n https://symfony.com/schema/dic/symfony/symfony-1.0.xsd\"\u0026gt;\n\n \u0026lt;framework:config\u0026gt;\n \u0026lt;framework:messenger\u0026gt;\n \u0026lt;!-- ... other transports --\u0026gt;\n\n \u0026lt;framework:transport name=\"sync\" dsn=\"sync://\"/\u0026gt;\n\n \u0026lt;framework:routing message-class=\"App\\Message\\SmsNotification\"\u0026gt;\n \u0026lt;framework:sender service=\"sync\"/\u0026gt;\n \u0026lt;/framework:routing\u0026gt;\n \u0026lt;/framework:messenger\u0026gt;\n \u0026lt;/framework:config\u0026gt;\n \u0026lt;/container\u0026gt;\n\n .. code-block:: php\n\n // config/packages/messenger.php\n $container-\u0026gt;loadFromExtension('framework', [\n 'messenger' =\u0026gt; [\n 'transports' =\u0026gt; [\n // ... other transports\n\n 'sync' =\u0026gt; 'sync://',\n ],\n 'routing' =\u0026gt; [\n 'App\\Message\\SmsNotification' =\u0026gt; 'sync',\n ],\n ],\n ]);\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-creating-your-own-transport\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCreating your Own Transport\u003c/h4\u003e\u003ca id=\"user-content-creating-your-own-transport\" class=\"anchor\" aria-label=\"Permalink: Creating your Own Transport\" href=\"#creating-your-own-transport\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eYou can also create your own transport if you need to send or receive messages\nfrom something that is not supported. See \u003ca href=\"#id19\"\u003e\u003cspan id=\"user-content-id20\"\u003e:doc:`/messenger/custom-transport`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003ca name=\"user-content-consuming-messages-running-the-worker\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eConsuming Messages (Running the Worker)\u003c/h3\u003e\u003ca id=\"user-content-consuming-messages-running-the-worker\" class=\"anchor\" aria-label=\"Permalink: Consuming Messages (Running the Worker)\" href=\"#consuming-messages-running-the-worker\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eOnce your messages have been routed, in most cases, you'll need to \"consume\" them.\nYou can do this with the \u003ccode\u003emessenger:consume\u003c/code\u003e command:\u003c/p\u003e\n\u003cpre lang=\"terminal\"\u003e$ php bin/console messenger:consume async\n\n# use -vv to see details about what's happening\n$ php bin/console messenger:consume async -vv\n\u003c/pre\u003e\n\u003cpre\u003e.. versionadded:: 4.3\n\n The ``messenger:consume`` command was renamed in Symfony 4.3 (previously it\n was called ``messenger:consume-messages``).\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThe first argument is the receiver's name (or service id if you routed to a\ncustom service). By default, the command will run forever: looking for new messages\non your transport and handling them. This command is called your \"worker\".\u003c/p\u003e\n\u003ca name=\"user-content-deploying-to-production\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDeploying to Production\u003c/h4\u003e\u003ca id=\"user-content-deploying-to-production\" class=\"anchor\" aria-label=\"Permalink: Deploying to Production\" href=\"#deploying-to-production\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eOn production, there are a few important things to think about:\u003c/p\u003e\n\u003cdl\u003e\n\u003cdt\u003e\u003cstrong\u003eUse Supervisor to keep your worker(s) running\u003c/strong\u003e\u003c/dt\u003e\n\u003cdd\u003eYou'll want one or more \"workers\" running at all times. To do that, use a\nprocess control system like \u003ca href=\"#id21\"\u003e\u003cspan id=\"user-content-id22\"\u003e:ref:`Supervisor \u0026lt;messenger-supervisor\u0026gt;`\u003c/span\u003e\u003c/a\u003e.\u003c/dd\u003e\n\u003cdt\u003e\u003cstrong\u003eDon't Let Workers Run Forever\u003c/strong\u003e\u003c/dt\u003e\n\u003cdd\u003eSome services (like Doctrine's EntityManager) will consume more memory\nover time. So, instead of allowing your worker to run forever, use a flag\nlike \u003ccode\u003emessenger:consume --limit=10\u003c/code\u003e to tell your worker to only handle 10\nmessages before exiting (then Supervisor will create a new process). There\nare also other options like \u003ccode\u003e--memory-limit=128M\u003c/code\u003e and \u003ccode\u003e--time-limit=3600\u003c/code\u003e.\u003c/dd\u003e\n\u003cdt\u003e\u003cstrong\u003eRestart Workers on Deploy\u003c/strong\u003e\u003c/dt\u003e\n\u003cdd\u003eEach time you deploy, you'll need to restart all your worker processes so\nthat they see the newly deployed code. To do this, run \u003ccode\u003emessenger:stop-workers\u003c/code\u003e\non deploy. This will signal to each worker that it should finish the message\nit's currently handling and shut down gracefully. Then, Supervisor will create\nnew worker processes. The command uses the \u003ca href=\"#id23\"\u003e\u003cspan id=\"user-content-id24\"\u003e:ref:`app \u0026lt;cache-configuration-with-frameworkbundle\u0026gt;`\u003c/span\u003e\u003c/a\u003e\ncache internally - so make sure this is configured to use an adapter you like.\u003c/dd\u003e\n\u003c/dl\u003e\n\u003ca name=\"user-content-prioritized-transports\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePrioritized Transports\u003c/h4\u003e\u003ca id=\"user-content-prioritized-transports\" class=\"anchor\" aria-label=\"Permalink: Prioritized Transports\" href=\"#prioritized-transports\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSometimes certain types of messages should have a higher priority and be handled\nbefore others. To make this possible, you can create multiple transports and route\ndifferent messages to them. For example:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # config/packages/messenger.yaml\n framework:\n messenger:\n transports:\n async_priority_high:\n dsn: '%env(MESSENGER_TRANSPORT_DSN)%'\n options:\n # queue_name is specific to the doctrine transport\n queue_name: high\n\n # for AMQP send to a separate exchange then queue\n #exchange:\n # name: high\n #queues:\n # messages_high: ~\n # or redis try \"group\"\n async_priority_low:\n dsn: '%env(MESSENGER_TRANSPORT_DSN)%'\n options:\n queue_name: low\n\n routing:\n 'App\\Message\\SmsNotification': async_priority_low\n 'App\\Message\\NewUserWelcomeEmail': async_priority_high\n\n .. code-block:: xml\n\n \u0026lt;!-- config/packages/messenger.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\" ?\u0026gt;\n \u0026lt;container xmlns=\"http://symfony.com/schema/dic/services\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:framework=\"http://symfony.com/schema/dic/symfony\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n https://symfony.com/schema/dic/services/services-1.0.xsd\n http://symfony.com/schema/dic/symfony\n https://symfony.com/schema/dic/symfony/symfony-1.0.xsd\"\u0026gt;\n\n \u0026lt;framework:config\u0026gt;\n \u0026lt;framework:messenger\u0026gt;\n \u0026lt;framework:transport name=\"async_priority_high\" dsn=\"%env(MESSENGER_TRANSPORT_DSN)%\"\u0026gt;\n \u0026lt;option key=\"queue_name\"\u0026gt;high\u0026lt;/option\u0026gt;\n \u0026lt;/framework:transport\u0026gt;\n \u0026lt;framework:transport name=\"async_priority_low\" dsn=\"%env(MESSENGER_TRANSPORT_DSN)%\"\u0026gt;\n \u0026lt;option key=\"queue_name\"\u0026gt;low\u0026lt;/option\u0026gt;\n \u0026lt;/framework:transport\u0026gt;\n\n \u0026lt;framework:routing message-class=\"App\\Message\\SmsNotification\"\u0026gt;\n \u0026lt;framework:sender service=\"async_priority_low\"/\u0026gt;\n \u0026lt;/framework:routing\u0026gt;\n \u0026lt;framework:routing message-class=\"App\\Message\\NewUserWelcomeEmail\"\u0026gt;\n \u0026lt;framework:sender service=\"async_priority_high\"/\u0026gt;\n \u0026lt;/framework:routing\u0026gt;\n \u0026lt;/framework:messenger\u0026gt;\n \u0026lt;/framework:config\u0026gt;\n \u0026lt;/container\u0026gt;\n\n .. code-block:: php\n\n // config/packages/messenger.php\n $container-\u0026gt;loadFromExtension('framework', [\n 'messenger' =\u0026gt; [\n 'transports' =\u0026gt; [\n 'async_priority_high' =\u0026gt; [\n 'dsn' =\u0026gt; '%env(MESSENGER_TRANSPORT_DSN)%',\n 'options' =\u0026gt; [\n 'queue_name' =\u0026gt; 'high',\n ],\n ],\n 'async_priority_low' =\u0026gt; [\n 'dsn' =\u0026gt; '%env(MESSENGER_TRANSPORT_DSN)%',\n 'options' =\u0026gt; [\n 'queue_name' =\u0026gt; 'low',\n ],\n ],\n ],\n 'routing' =\u0026gt; [\n 'App\\Message\\SmsNotification' =\u0026gt; 'async_priority_low',\n 'App\\Message\\NewUserWelcomeEmail' =\u0026gt; 'async_priority_high',\n ],\n ],\n ]);\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eYou can then run individual workers for each transport or instruct one worker\nto handle messages in a priority order:\u003c/p\u003e\n\u003cpre lang=\"terminal\"\u003e$ php bin/console messenger:consume async_priority_high async_priority_low\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThe worker will always first look for messages waiting on \u003ccode\u003easync_priority_high\u003c/code\u003e. If\nthere are none, \u003cem\u003ethen\u003c/em\u003e it will consume messages from \u003ccode\u003easync_priority_low\u003c/code\u003e.\u003c/p\u003e\n\u003ca name=\"user-content-supervisor-configuration\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSupervisor Configuration\u003c/h4\u003e\u003ca id=\"user-content-supervisor-configuration\" class=\"anchor\" aria-label=\"Permalink: Supervisor Configuration\" href=\"#supervisor-configuration\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSupervisor is a great tool to guarantee that your worker process(es) is\n\u003cem\u003ealways\u003c/em\u003e running (even if it closes due to failure, hitting a message limit\nor thanks to \u003ccode\u003emessenger:stop-workers\u003c/code\u003e). You can install it on Ubuntu, for\nexample, via:\u003c/p\u003e\n\u003cpre lang=\"terminal\"\u003e$ sudo apt-get install supervisor\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eSupervisor configuration files typically live in a \u003ccode\u003e/etc/supervisor/conf.d\u003c/code\u003e\ndirectory. For example, you can create a new \u003ccode\u003emessenger-worker.conf\u003c/code\u003e file\nthere to make sure that 2 instances of \u003ccode\u003emessenger:consume\u003c/code\u003e are running at all\ntimes:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-ini notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\";/etc/supervisor/conf.d/messenger-worker.conf\n[program:messenger-consume]\ncommand=php /path/to/your/app/bin/console messenger:consume async --time-limit=3600\nuser=ubuntu\nnumprocs=2\nautostart=true\nautorestart=true\nprocess_name=%(program_name)s_%(process_num)02d\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e;\u003c/span\u003e/etc/supervisor/conf.d/messenger-worker.conf\u003c/span\u003e\n\u003cspan class=\"pl-en\"\u003e[program:messenger-consume]\u003c/span\u003e\n\u003cspan class=\"pl-k\"\u003ecommand\u003c/span\u003e=php /path/to/your/app/bin/console messenger:consume async --\u003cspan class=\"pl-k\"\u003etime-limit\u003c/span\u003e=3600\n\u003cspan class=\"pl-k\"\u003euser\u003c/span\u003e=ubuntu\n\u003cspan class=\"pl-k\"\u003enumprocs\u003c/span\u003e=2\n\u003cspan class=\"pl-k\"\u003eautostart\u003c/span\u003e=true\n\u003cspan class=\"pl-k\"\u003eautorestart\u003c/span\u003e=true\n\u003cspan class=\"pl-k\"\u003eprocess_name\u003c/span\u003e=%(program_name)s_%(process_num)02d\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eChange the \u003ccode\u003easync\u003c/code\u003e argument to use the name of your transport (or transports)\nand \u003ccode\u003euser\u003c/code\u003e to the Unix user on your server. Next, tell Supervisor to read your\nconfig and start your workers:\u003c/p\u003e\n\u003cpre lang=\"terminal\"\u003e$ sudo supervisorctl reread\n\n$ sudo supervisorctl update\n\n$ sudo supervisorctl start messenger-consume:*\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eSee the \u003ca href=\"http://supervisord.org/\" rel=\"nofollow\"\u003eSupervisor docs\u003c/a\u003e for more details.\u003c/p\u003e\n\u003ca name=\"user-content-retries-failures\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eRetries \u0026amp; Failures\u003c/h3\u003e\u003ca id=\"user-content-retries--failures\" class=\"anchor\" aria-label=\"Permalink: Retries \u0026amp; Failures\" href=\"#retries--failures\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIf an exception is thrown while consuming a message from a transport it will\nautomatically be re-sent to the transport to be tried again. By default, a message\nwill be retried 3 times before being discarded or\n\u003ca href=\"#id25\"\u003e\u003cspan id=\"user-content-id26\"\u003e:ref:`sent to the failure transport \u0026lt;messenger-failure-transport\u0026gt;`\u003c/span\u003e\u003c/a\u003e. Each retry\nwill also be delayed, in case the failure was due to a temporary issue. All of\nthis is configurable for each transport:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # config/packages/messenger.yaml\n framework:\n messenger:\n transports:\n async_priority_high:\n dsn: '%env(MESSENGER_TRANSPORT_DSN)%'\n\n # default configuration\n retry_strategy:\n max_retries: 3\n # milliseconds delay\n delay: 1000\n # causes the delay to be higher before each retry\n # e.g. 1 second delay, 2 seconds, 4 seconds\n multiplier: 2\n max_delay: 0\n # override all of this with a service that\n # implements Symfony\\Component\\Messenger\\Retry\\RetryStrategyInterface\n # service: null\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-avoiding-retrying\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eAvoiding Retrying\u003c/h4\u003e\u003ca id=\"user-content-avoiding-retrying\" class=\"anchor\" aria-label=\"Permalink: Avoiding Retrying\" href=\"#avoiding-retrying\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSometimes handling a message might fail in a way that you \u003cem\u003eknow\u003c/em\u003e is permanent\nand should not be retried. If you throw\n\u003ca href=\"#id27\"\u003e\u003cspan id=\"user-content-id28\"\u003e:class:`Symfony\\\\Component\\\\Messenger\\\\Exception\\\\UnrecoverableMessageHandlingException`\u003c/span\u003e\u003c/a\u003e,\nthe message will not be retried.\u003c/p\u003e\n\u003ca name=\"user-content-saving-retrying-failed-messages\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSaving \u0026amp; Retrying Failed Messages\u003c/h4\u003e\u003ca id=\"user-content-saving--retrying-failed-messages\" class=\"anchor\" aria-label=\"Permalink: Saving \u0026amp; Retrying Failed Messages\" href=\"#saving--retrying-failed-messages\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIf a message fails it is retried multiple times (\u003ccode\u003emax_retries\u003c/code\u003e) and then will\nbe discarded. To avoid this happening, you can instead configure a \u003ccode\u003efailure_transport\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # config/packages/messenger.yaml\n framework:\n messenger:\n # after retrying, messages will be sent to the \"failed\" transport\n failure_transport: failed\n\n transports:\n # ... other transports\n\n failed: 'doctrine://default?queue_name=failed'\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eIn this example, if handling a message fails 3 times (default \u003ccode\u003emax_retries\u003c/code\u003e),\nit will then be sent to the \u003ccode\u003efailed\u003c/code\u003e transport. While you \u003cem\u003ecan\u003c/em\u003e use\n\u003ccode\u003emessenger:consume failed\u003c/code\u003e to consume this like a normal transport, you'll\nusually want to manually view the messages in the failure transport and choose\nto retry them:\u003c/p\u003e\n\u003cpre lang=\"terminal\"\u003e# see all messages in the failure transport\n$ php bin/console messenger:failed:show\n\n# see details about a specific failure\n$ php bin/console messenger:failed:show 20 -vv\n\n# view and retry messages one-by-one\n$ php bin/console messenger:failed:retry -vv\n\n# retry specific messages\n$ php bin/console messenger:failed:retry 20 30 --force\n\n# remove a message without retrying it\n$ php bin/console messenger:failed:remove 20\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eIf the message fails again, it will be re-sent back to the failure transport\ndue to the normal \u003ca href=\"#id29\"\u003e\u003cspan id=\"user-content-id30\"\u003e:ref:`retry rules \u0026lt;messenger-retries-failures\u0026gt;`\u003c/span\u003e\u003c/a\u003e. Once the max\nretry has been hit, the message will be discarded permanently.\u003c/p\u003e\n\u003ca name=\"user-content-transport-configuration\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTransport Configuration\u003c/h3\u003e\u003ca id=\"user-content-transport-configuration\" class=\"anchor\" aria-label=\"Permalink: Transport Configuration\" href=\"#transport-configuration\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eMessenger supports a number of different transport types, each with their own\noptions.\u003c/p\u003e\n\u003ca name=\"user-content-amqp-transport\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eAMQP Transport\u003c/h4\u003e\u003ca id=\"user-content-amqp-transport\" class=\"anchor\" aria-label=\"Permalink: AMQP Transport\" href=\"#amqp-transport\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003eamqp\u003c/code\u003e transport configuration looks like this:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"# .env\nMESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e .env\u003c/span\u003e\nMESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eTo use Symfony's built-in AMQP transport, you need the AMQP PHP extension.\u003c/p\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eNote\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eBy default, the transport will automatically create any exchanges, queues and\nbinding keys that are needed. That can be disabled, but some functionality\nmay not work correctly (like delayed queues).\u003c/p\u003e\n\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe transport has a number of other options, including ways to configure\nthe exchange, queues binding keys and more. See the documentation on\n\u003ca href=\"#id31\"\u003e\u003cspan id=\"user-content-id32\"\u003e:class:`Symfony\\\\Component\\\\Messenger\\\\Transport\\\\AmqpExt\\\\Connection`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eYou can also configure AMQP-specific settings on your message by adding\n\u003ca href=\"#id33\"\u003e\u003cspan id=\"user-content-id34\"\u003e:class:`Symfony\\\\Component\\\\Messenger\\\\Transport\\\\AmqpExt\\\\AmqpStamp`\u003c/span\u003e\u003c/a\u003e to\nyour Envelope:\u003c/p\u003e\n\u003cpre\u003euse Symfony\\Component\\Messenger\\Transport\\AmqpExt\\AmqpStamp;\n// ...\n\n$attributes = [];\n$bus-\u0026gt;dispatch(new SmsNotification(), [\n new AmqpStamp('custom-routing-key', AMQP_NOPARAM, $attributes)\n]);\n\u003c/pre\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eCaution!\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe consumers do not show up in an admin panel as this transport does not rely on\n\u003ccode\u003e\\AmqpQueue::consume()\u003c/code\u003e which is blocking. Having a blocking receiver makes\nthe \u003ccode\u003e--time-limit/--memory-limit\u003c/code\u003e options of the \u003ccode\u003emessenger:consume\u003c/code\u003e command as well as\nthe \u003ccode\u003emessenger:stop-workers\u003c/code\u003e command inefficient, as they all rely on the fact that\nthe receiver returns immediately no matter if it finds a message or not. The consume\nworker is responsible for iterating until it receives a message to handle and/or until one\nof the stop conditions is reached. Thus, the worker's stop logic cannot be reached if it\nis stuck in a blocking call.\u003c/p\u003e\n\u003c/div\u003e\n\u003ca name=\"user-content-doctrine-transport\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDoctrine Transport\u003c/h4\u003e\u003ca id=\"user-content-doctrine-transport\" class=\"anchor\" aria-label=\"Permalink: Doctrine Transport\" href=\"#doctrine-transport\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cpre\u003e.. versionadded:: 4.3\n\n The Doctrine transport was introduced in Symfony 4.3.\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThe Doctrine transport can be used to store messages in a database table.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"# .env\nMESSENGER_TRANSPORT_DSN=doctrine://default\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e .env\u003c/span\u003e\nMESSENGER_TRANSPORT_DSN=doctrine://default\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe format is \u003ccode\u003edoctrine://\u0026lt;connection_name\u0026gt;\u003c/code\u003e, in case you have multiple connections\nand want to use one other than the \"default\". The transport will automatically create\na table named \u003ccode\u003emessenger_messages\u003c/code\u003e (this is configurable) when the transport is\nfirst used. You can disable that with the \u003ccode\u003eauto_setup\u003c/code\u003e option and set the table\nup manually by calling the \u003ccode\u003emessenger:setup-transports\u003c/code\u003e command.\u003c/p\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eTip\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eTo avoid tools like Doctrine Migrations from trying to remove this table because\nit's not part of your normal schema, you can set the \u003ccode\u003eschema_filter\u003c/code\u003e option:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-yaml notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"# config/packages/doctrine.yaml\ndoctrine:\n dbal:\n schema_filter: '~^(?!messenger_messages)~'\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e config/packages/doctrine.yaml\u003c/span\u003e\n\u003cspan class=\"pl-ent\"\u003edoctrine\u003c/span\u003e:\n \u003cspan class=\"pl-ent\"\u003edbal\u003c/span\u003e:\n \u003cspan class=\"pl-ent\"\u003eschema_filter\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e~^(?!messenger_messages)~\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe transport has a number of options:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # config/packages/messenger.yaml\n framework:\n messenger:\n transports:\n async_priority_high: \"%env(MESSENGER_TRANSPORT_DSN)%?queue_name=high_priority\"\n async_normal:\n dsn: \"%env(MESSENGER_TRANSPORT_DSN)%\"\n options:\n queue_name: normal_priority\n\n .. code-block:: xml\n\n \u0026lt;!-- config/packages/messenger.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\" ?\u0026gt;\n \u0026lt;container xmlns=\"http://symfony.com/schema/dic/services\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:framework=\"http://symfony.com/schema/dic/symfony\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n https://symfony.com/schema/dic/services/services-1.0.xsd\n http://symfony.com/schema/dic/symfony\n https://symfony.com/schema/dic/symfony/symfony-1.0.xsd\"\u0026gt;\n\n \u0026lt;framework:config\u0026gt;\n \u0026lt;framework:messenger\u0026gt;\n \u0026lt;framework:transport name=\"async_priority_high\" dsn=\"%env(MESSENGER_TRANSPORT_DSN)%?queue_name=high_priority\"/\u0026gt;\n \u0026lt;framework:transport name=\"async_priority_low\" dsn=\"%env(MESSENGER_TRANSPORT_DSN)%\"\u0026gt;\n \u0026lt;framework:option queue_name=\"normal_priority\"/\u0026gt;\n \u0026lt;/framework:transport\u0026gt;\n \u0026lt;/framework:messenger\u0026gt;\n \u0026lt;/framework:config\u0026gt;\n \u0026lt;/container\u0026gt;\n\n .. code-block:: php\n\n // config/packages/messenger.php\n $container-\u0026gt;loadFromExtension('framework', [\n 'messenger' =\u0026gt; [\n 'transports' =\u0026gt; [\n 'async_priority_high' =\u0026gt; 'dsn' =\u0026gt; '%env(MESSENGER_TRANSPORT_DSN)%?queue_name=high_priority',\n 'async_priority_low' =\u0026gt; [\n 'dsn' =\u0026gt; '%env(MESSENGER_TRANSPORT_DSN)%',\n 'options' =\u0026gt; [\n 'queue_name' =\u0026gt; 'normal_priority'\n ]\n ],\n ],\n ],\n ]);\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eOptions defined under \u003ccode\u003eoptions\u003c/code\u003e take precedence over ones defined in the DSN.\u003c/p\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\n\n\n\n\n\u003cthead valign=\"bottom\"\u003e\n\u003ctr\u003e\u003cth\u003eOption\u003c/th\u003e\n\u003cth\u003eDescription\u003c/th\u003e\n\u003cth\u003eDefault\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody valign=\"top\"\u003e\n\u003ctr\u003e\u003ctd\u003etable_name\u003c/td\u003e\n\u003ctd\u003eName of the table\u003c/td\u003e\n\u003ctd\u003emessenger_messages\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003equeue_name\u003c/td\u003e\n\u003ctd\u003eName of the queue (a column in the\ntable, to use one table for\nmultiple transports)\u003c/td\u003e\n\u003ctd\u003edefault\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eredeliver_timeout\u003c/td\u003e\n\u003ctd\u003eTimeout before retrying a message\nthat's in the queue but in the\n\"handling\" state (if a worker died\nfor some reason, this will occur,\neventually you should retry the\nmessage) - in seconds.\u003c/td\u003e\n\u003ctd\u003e3600\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eauto_setup\u003c/td\u003e\n\u003ctd\u003eWhether the table should be created\nautomatically during send / get.\u003c/td\u003e\n\u003ctd\u003etrue\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003ca name=\"user-content-redis-transport\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eRedis Transport\u003c/h4\u003e\u003ca id=\"user-content-redis-transport\" class=\"anchor\" aria-label=\"Permalink: Redis Transport\" href=\"#redis-transport\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cpre\u003e.. versionadded:: 4.3\n\n The Redis transport was introduced in Symfony 4.3.\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThe Redis transport uses \u003ca href=\"https://redis.io/topics/streams-intro\" rel=\"nofollow\"\u003estreams\u003c/a\u003e to queue messages.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"# .env\nMESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages\n# Full DSN Example\nMESSENGER_TRANSPORT_DSN=redis://password@localhost:6379/messages/symfony/consumer?auto_setup=true\u0026amp;serializer=1\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e .env\u003c/span\u003e\nMESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages\n\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e Full DSN Example\u003c/span\u003e\nMESSENGER_TRANSPORT_DSN=redis://password@localhost:6379/messages/symfony/consumer\u003cspan class=\"pl-k\"\u003e?\u003c/span\u003eauto_setup=true\u003cspan class=\"pl-k\"\u003e\u0026amp;\u003c/span\u003eserializer=1\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eTo use the Redis transport, you will need the Redis PHP extension (^4.3) and\na running Redis server (^5.0).\u003c/p\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eCaution!\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe Redis transport does not support \"delayed\" messages.\u003c/p\u003e\n\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eA number of options can be configured via the DSN or via the \u003ccode\u003eoptions\u003c/code\u003e key\nunder the transport in \u003ccode\u003emessenger.yaml\u003c/code\u003e:\u003c/p\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\n\n\n\n\n\u003cthead valign=\"bottom\"\u003e\n\u003ctr\u003e\u003cth\u003eOption\u003c/th\u003e\n\u003cth\u003eDescription\u003c/th\u003e\n\u003cth\u003eDefault\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody valign=\"top\"\u003e\n\u003ctr\u003e\u003ctd\u003estream\u003c/td\u003e\n\u003ctd\u003eThe Redis stream name\u003c/td\u003e\n\u003ctd\u003emessages\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003egroup\u003c/td\u003e\n\u003ctd\u003eThe Redis consumer group name\u003c/td\u003e\n\u003ctd\u003esymfony\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003econsumer\u003c/td\u003e\n\u003ctd\u003eConsumer name used in Redis\u003c/td\u003e\n\u003ctd\u003econsumer\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eauto_setup\u003c/td\u003e\n\u003ctd\u003eCreate the Redis group automatically?\u003c/td\u003e\n\u003ctd\u003etrue\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eauth\u003c/td\u003e\n\u003ctd\u003eThe Redis password\u003c/td\u003e\n\u003ctd\u003e \u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eserializer\u003c/td\u003e\n\u003ctd\u003eHow to serialize the final payload\nin Redis (the\n\u003ccode\u003eRedis::OPT_SERIALIZER\u003c/code\u003e option)\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eRedis::SERIALIZER_PHP\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003ca name=\"user-content-in-memory-transport\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eIn Memory Transport\u003c/h4\u003e\u003ca id=\"user-content-in-memory-transport\" class=\"anchor\" aria-label=\"Permalink: In Memory Transport\" href=\"#in-memory-transport\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cpre\u003e.. versionadded:: 4.3\n\n The ``in-memory`` transport was introduced in Symfony 4.3.\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003ein-memory\u003c/code\u003e transport does not actually deliver messages. Instead, it\nholds them in memory during the request, which can be useful for testing.\nFor example, if you have an \u003ccode\u003easync_priority_normal\u003c/code\u003e transport, you could\noverride it in the \u003ccode\u003etest\u003c/code\u003e environment to use this transport:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-yaml notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"# config/packages/test/messenger.yaml\nframework:\n messenger:\n transports:\n async_priority_normal: 'in-memory:///'\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e config/packages/test/messenger.yaml\u003c/span\u003e\n\u003cspan class=\"pl-ent\"\u003eframework\u003c/span\u003e:\n \u003cspan class=\"pl-ent\"\u003emessenger\u003c/span\u003e:\n \u003cspan class=\"pl-ent\"\u003etransports\u003c/span\u003e:\n \u003cspan class=\"pl-ent\"\u003easync_priority_normal\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003ein-memory:///\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThen, while testing, messages will \u003cem\u003enot\u003c/em\u003e be delivered to the real transport.\nEven better, in a test, you can check that exactly one message was sent\nduring a request:\u003c/p\u003e\n\u003cpre\u003e// tests/DefaultControllerTest.php\nnamespace App\\Tests;\n\nuse Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestCase;\nuse Symfony\\Component\\Messenger\\Transport\\InMemoryTransport;\n\nclass DefaultControllerTest extends WebTestCase\n{\n public function testSomething()\n {\n $client = static::createClient();\n // ...\n\n $this-\u0026gt;assertSame(200, $client-\u0026gt;getResponse()-\u0026gt;getStatusCode());\n\n /* @var InMemoryTransport $transport */\n $transport = self::$container-\u0026gt;get('messenger.transport.async_priority_normal');\n $this-\u0026gt;assertCount(1, $transport-\u0026gt;get());\n }\n}\n\u003c/pre\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eNote\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAll \u003ccode\u003ein-memory\u003c/code\u003e transports will be reset automatically after each test \u003cstrong\u003ein\u003c/strong\u003e\ntest classes extending\n\u003ca href=\"#id35\"\u003e\u003cspan id=\"user-content-id36\"\u003e:class:`Symfony\\\\Bundle\\\\FrameworkBundle\\\\Test\\\\KernelTestCase`\u003c/span\u003e\u003c/a\u003e\nor \u003ca href=\"#id37\"\u003e\u003cspan id=\"user-content-id38\"\u003e:class:`Symfony\\\\Bundle\\\\FrameworkBundle\\\\Test\\\\WebTestCase`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003c/div\u003e\n\u003ca name=\"user-content-serializing-messages\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSerializing Messages\u003c/h4\u003e\u003ca id=\"user-content-serializing-messages\" class=\"anchor\" aria-label=\"Permalink: Serializing Messages\" href=\"#serializing-messages\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cpre\u003e.. versionadded:: 4.3\n\n The default serializer changed in 4.3 from the Symfony serializer to the\n native PHP serializer. Existing applications should configure their transports\n to use the Symfony serializer to avoid losing already-queued messages after\n upgrading.\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eWhen messages are sent to (and received from) a transport, they're serialized\nusing PHP's native \u003ccode\u003eserialize()\u003c/code\u003e \u0026amp; \u003ccode\u003eunserialize()\u003c/code\u003e functions. You can change\nthis globally (or for each transport) to a service that implements\n\u003ca href=\"#id39\"\u003e\u003cspan id=\"user-content-id40\"\u003e:class:`Symfony\\\\Component\\\\Messenger\\\\Transport\\\\Serialization\\\\SerializerInterface`\u003c/span\u003e\u003c/a\u003e:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # config/packages/messenger.yaml\n framework:\n messenger:\n serializer:\n default_serializer: messenger.transport.symfony_serializer\n symfony_serializer:\n format: json\n context: { }\n\n transports:\n async_priority_normal:\n dsn: # ...\n serializer: messenger.transport.symfony_serializer\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003emessenger.transport.symfony_serializer\u003c/code\u003e is a built-in service that uses\nthe \u003ca href=\"#id41\"\u003e\u003cspan id=\"user-content-id42\"\u003e:doc:`Serializer component \u0026lt;/serializer\u0026gt;`\u003c/span\u003e\u003c/a\u003e and can be configured in a few ways.\nIf you \u003cem\u003edo\u003c/em\u003e choose to use the Symfony serializer, you can control the context\non a case-by-case basis via the \u003ca href=\"#id43\"\u003e\u003cspan id=\"user-content-id44\"\u003e:class:`Symfony\\\\Component\\\\Messenger\\\\Stamp\\\\SerializerStamp`\u003c/span\u003e\u003c/a\u003e\n(see \u003ca href=\"#envelopes-stamps\"\u003eEnvelopes \u0026amp; Stamps\u003c/a\u003e).\u003c/p\u003e\n\u003ca name=\"user-content-customizing-handlers\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCustomizing Handlers\u003c/h3\u003e\u003ca id=\"user-content-customizing-handlers\" class=\"anchor\" aria-label=\"Permalink: Customizing Handlers\" href=\"#customizing-handlers\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003ca name=\"user-content-manually-configuring-handlers\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eManually Configuring Handlers\u003c/h4\u003e\u003ca id=\"user-content-manually-configuring-handlers\" class=\"anchor\" aria-label=\"Permalink: Manually Configuring Handlers\" href=\"#manually-configuring-handlers\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSymfony will normally \u003ca href=\"#id45\"\u003e\u003cspan id=\"user-content-id46\"\u003e:ref:`find and register your handler automatically \u0026lt;messenger-handler\u0026gt;`\u003c/span\u003e\u003c/a\u003e.\nBut, you can also configure a handler manually - and pass it some extra config -\nby tagging the handler service with \u003ccode\u003emessenger.message_handler\u003c/code\u003e\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # config/services.yaml\n services:\n App\\MessageHandler\\SmsNotificationHandler:\n tags: [messenger.message_handler]\n\n # or configure with options\n tags:\n -\n name: messenger.message_handler\n # only needed if can't be guessed by type-hint\n handles: App\\Message\\SmsNotification\n\n # options returned by getHandledMessages() are supported here\n\n .. code-block:: xml\n\n \u0026lt;!-- config/services.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\" ?\u0026gt;\n \u0026lt;container xmlns=\"http://symfony.com/schema/dic/services\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n https://symfony.com/schema/dic/services/services-1.0.xsd\"\u0026gt;\n\n \u0026lt;services\u0026gt;\n \u0026lt;service id=\"App\\MessageHandler\\SmsNotificationHandler\"\u0026gt;\n \u0026lt;tag name=\"messenger.message_handler\"/\u0026gt;\n \u0026lt;/service\u0026gt;\n \u0026lt;/services\u0026gt;\n \u0026lt;/container\u0026gt;\n\n .. code-block:: php\n\n // config/services.php\n use App\\MessageHandler\\SmsNotificationHandler;\n\n $container-\u0026gt;register(SmsNotificationHandler::class)\n -\u0026gt;addTag('messenger.message_handler');\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-handler-subscriber-options\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eHandler Subscriber \u0026amp; Options\u003c/h4\u003e\u003ca id=\"user-content-handler-subscriber--options\" class=\"anchor\" aria-label=\"Permalink: Handler Subscriber \u0026amp; Options\" href=\"#handler-subscriber--options\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eA handler class can handle multiple messages or configure itself by implementing\n\u003ca href=\"#id47\"\u003e\u003cspan id=\"user-content-id48\"\u003e:class:`Symfony\\\\Component\\\\Messenger\\\\Handler\\\\MessageSubscriberInterface`\u003c/span\u003e\u003c/a\u003e:\u003c/p\u003e\n\u003cpre\u003e// src/MessageHandler/SmsNotificationHandler.php\nnamespace App\\MessageHandler;\n\nuse App\\Message\\OtherSmsNotification;\nuse App\\Message\\SmsNotification;\nuse Symfony\\Component\\Messenger\\Handler\\MessageSubscriberInterface;\n\nclass SmsNotificationHandler implements MessageSubscriberInterface\n{\n public function __invoke(SmsNotification $message)\n {\n // ...\n }\n\n public function handleOtherSmsNotification(OtherSmsNotification $message)\n {\n // ...\n }\n\n public static function getHandledMessages(): iterable\n {\n // handle this message on __invoke\n yield SmsNotification::class;\n\n // also handle this message on handleOtherSmsNotification\n yield OtherSmsNotification::class =\u0026gt; [\n 'method' =\u0026gt; 'handleOtherSmsNotification',\n //'priority' =\u0026gt; 0,\n //'bus' =\u0026gt; 'messenger.bus.default',\n ];\n }\n}\n\u003c/pre\u003e\n\u003ca name=\"user-content-binding-handlers-to-different-transports\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eBinding Handlers to Different Transports\u003c/h4\u003e\u003ca id=\"user-content-binding-handlers-to-different-transports\" class=\"anchor\" aria-label=\"Permalink: Binding Handlers to Different Transports\" href=\"#binding-handlers-to-different-transports\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eEach message can have multiple handlers, and when a message is consumed\n\u003cem\u003eall\u003c/em\u003e of its handlers are called. But you can also configure a handler to only\nbe called when it's received from a \u003cem\u003especific\u003c/em\u003e transport. This allows you to\nhave a single message where each handler is called by a different \"worker\"\nthat's consuming a different transport.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eSuppose you have an \u003ccode\u003eUploadedImage\u003c/code\u003e message with two handlers:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eThumbnailUploadedImageHandler\u003c/code\u003e: you want this to be handled by\na transport called \u003ccode\u003eimage_transport\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u00 91D9 3eNotifyAboutNewUploadedImageHandler\u003c/code\u003e: you want this to be handled\nby a transport called \u003ccode\u003easync_priority_normal\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eTo do this, add the \u003ccode\u003efrom_transport\u003c/code\u003e option to each handler. For example:\u003c/p\u003e\n\u003cpre\u003e// src/MessageHandler/ThumbnailUploadedImageHandler.php\nnamespace App\\MessageHandler;\n\nuse App\\Message\\UploadedImage;\nuse Symfony\\Component\\Messenger\\Handler\\MessageSubscriberInterface;\n\nclass ThumbnailUploadedImageHandler implements MessageSubscriberInterface\n{\n public function __invoke(UploadedImage $uploadedImage)\n {\n // do some thumbnailing\n }\n\n public static function getHandledMessages(): iterable\n {\n yield UploadedImage::class =\u0026gt; [\n 'from_transport' =\u0026gt; 'image_transport',\n ];\n }\n}\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eAnd similarly:\u003c/p\u003e\n\u003cpre\u003e// src/MessageHandler/NotifyAboutNewUploadedImageHandler.php\n// ...\n\nclass NotifyAboutNewUploadedImageHandler implements MessageSubscriberInterface\n{\n // ...\n\n public static function getHandledMessages(): iterable\n {\n yield UploadedImage::class =\u0026gt; [\n 'from_transport' =\u0026gt; 'async_priority_normal',\n ];\n }\n}\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThen, make sure to \"route\" your message to \u003cem\u003eboth\u003c/em\u003e transports:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # config/packages/messenger.yaml\n framework:\n messenger:\n transports:\n async_priority_normal: # ...\n image_transport: # ...\n\n routing:\n # ...\n 'App\\Message\\UploadedImage': [image_transport, async_priority_normal]\n\n .. code-block:: xml\n\n \u0026lt;!-- config/packages/messenger.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\" ?\u0026gt;\n \u0026lt;container xmlns=\"http://symfony.com/schema/dic/services\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:framework=\"http://symfony.com/schema/dic/symfony\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n https://symfony.com/schema/dic/services/services-1.0.xsd\n http://symfony.com/schema/dic/symfony\n https://symfony.com/schema/dic/symfony/symfony-1.0.xsd\"\u0026gt;\n\n \u0026lt;framework:config\u0026gt;\n \u0026lt;framework:messenger\u0026gt;\n \u0026lt;framework:transport name=\"async_priority_normal\" dsn=\"...\"/\u0026gt;\n \u0026lt;framework:transport name=\"image_transport\" dsn=\"...\"/\u0026gt;\n\n \u0026lt;framework:routing message-class=\"App\\Message\\UploadedImage\"\u0026gt;\n \u0026lt;framework:sender service=\"image_transport\"/\u0026gt;\n \u0026lt;framework:sender service=\"async_priority_normal\"/\u0026gt;\n \u0026lt;/framework:routing\u0026gt;\n \u0026lt;/framework:messenger\u0026gt;\n \u0026lt;/framework:config\u0026gt;\n \u0026lt;/container\u0026gt;\n\n .. code-block:: php\n\n // config/packages/messenger.php\n $container-\u0026gt;loadFromExtension('framework', [\n 'messenger' =\u0026gt; [\n 'transports' =\u0026gt; [\n 'async_priority_normal' =\u0026gt; '...',\n 'image_transport' =\u0026gt; '...',\n ],\n 'routing' =\u0026gt; [\n 'App\\Message\\UploadedImage' =\u0026gt; ['image_transport', 'async_priority_normal']\n ]\n ],\n ]);\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eThat's it! You can now consume each transport:\u003c/p\u003e\n\u003cpre lang=\"terminal\"\u003e# will only call ThumbnailUploadedImageHandler when handling the message\n$ php bin/console messenger:consume image_transport -vv\n\n$ php bin/console messenger:consume async_priority_normal -vv\n\u003c/pre\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eCaution!\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIf a handler does \u003cem\u003enot\u003c/em\u003e have \u003ccode\u003efrom_transport\u003c/code\u003e config, it will be executed\non \u003cem\u003eevery\u003c/em\u003e transport that the message is received from.\u003c/p\u003e\n\u003c/div\u003e\n\u003ca name=\"user-content-extending-messenger\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eExtending Messenger\u003c/h3\u003e\u003ca id=\"user-content-extending-messenger\" class=\"anchor\" aria-label=\"Permalink: Extending Messenger\" href=\"#extending-messenger\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003ca name=\"user-content-envelopes-stamps\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eEnvelopes \u0026amp; Stamps\u003c/h4\u003e\u003ca id=\"user-content-envelopes--stamps\" class=\"anchor\" aria-label=\"Permalink: Envelopes \u0026amp; Stamps\" href=\"#envelopes--stamps\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eA message can be any PHP object. Sometimes, you may need to configure something\nextra about the message - like the way it should be handled inside AMQP or adding\na delay before the message should be handled. You can do that by adding a \"stamp\"\nto your message:\u003c/p\u003e\n\u003cpre\u003euse Symfony\\Component\\Messenger\\Envelope;\nuse Symfony\\Component\\Messenger\\MessageBusInterface;\nuse Symfony\\Component\\Messenger\\Stamp\\DelayStamp;\n\npublic function index(MessageBusInterface $bus)\n{\n $bus-\u0026gt;dispatch(new SmsNotification('...'), [\n // wait 5 seconds before processing\n new DelayStamp(5000)\n ]);\n\n // or explicitly create an Envelope\n $bus-\u0026gt;dispatch(new Envelope(new SmsNotification('...'), [\n new DelayStamp(5000)\n ]));\n\n // ...\n}\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eInternally, each message is wrapped in an \u003ccode\u003eEnvelope\u003c/code\u003e, which holds the message\nand stamps. You can create this manually or allow the message bus to do it. There\nare a variety of different stamps for different purposes and they're used internally\nto track information about a message - like the message bus that's handling it\nor if it's being retried after failure.\u003c/p\u003e\n\u003ca name=\"user-content-middleware\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eMiddleware\u003c/h4\u003e\u003ca id=\"user-content-middleware\" class=\"anchor\" aria-label=\"Permalink: Middleware\" href=\"#middleware\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWhat happens when you dispatch a message to a message bus depends on its\ncollection of middleware and their order. By default, the middleware configured\nfor each bus looks like this:\u003c/p\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eadd_bus_name_stamp_middleware\u003c/code\u003e - adds a stamp to record which bus this\nmessage was dispatched into;\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003edispatch_after_current_bus\u003c/code\u003e- see \u003ca href=\"#id49\"\u003e\u003cspan id=\"user-content-id50\"\u003e:doc:`/messenger/message-recorder`\u003c/span\u003e\u003c/a\u003e;\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003efailed_message_processing_middleware\u003c/code\u003e - processes messages that are being\nretried via the \u003ca href=\"#id51\"\u003e\u003cspan id=\"user-content-id52\"\u003e:ref:`failure transport \u0026lt;messenger-failure-transport\u0026gt;`\u003c/span\u003e\u003c/a\u003e to make\nthem properly function as if they were being received from their original transport;\u003c/li\u003e\n\u003cli\u003eYour own collection of \u003ca href=\"#middleware\"\u003emiddleware\u003c/a\u003e;\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esend_message\u003c/code\u003e - if routing is configured for the transport, this sends\nmessages to that transport and stops the middleware chain;\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ehandle_message\u003c/code\u003e - calls the message handler(s) for the given message.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eNote\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThese middleware names are actually shortcut names. The real service ids\nare prefixed with \u003ccode\u003emessenger.middleware.\u003c/code\u003e (e.g. \u003ccode\u003emessenger.middleware.handle_message\u003c/code\u003e).\u003c/p\u003e\n\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe middleware are executed when the message is dispatched but \u003cem\u003ealso\u003c/em\u003e again when\na message is received via the worker (for messages that were sent to a transport\nto be handled asynchronously). Keep this in mind if you create your own middleware.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eYou can add your own middleware to this list, or completely disable the default\nmiddleware and \u003cem\u003eonly\u003c/em\u003e include your own:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # config/packages/messenger.yaml\n framework:\n messenger:\n buses:\n messenger.bus.default:\n middleware:\n # service ids that implement Symfony\\Component\\Messenger\\Middleware\\MiddlewareInterface\n - 'App\\Middleware\\MyMiddleware'\n - 'App\\Middleware\\AnotherMiddleware'\n\n #default_middleware: false\n\n .. code-block:: xml\n\n \u0026lt;!-- config/packages/messenger.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\" ?\u0026gt;\n \u0026lt;container xmlns=\"http://symfony.com/schema/dic/services\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:framework=\"http://symfony.com/schema/dic/symfony\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n https://symfony.com/schema/dic/services/services-1.0.xsd\n http://symfony.com/schema/dic/symfony\n https://symfony.com/schema/dic/symfony/symfony-1.0.xsd\"\u0026gt;\n\n \u0026lt;framework:config\u0026gt;\n \u0026lt;framework:messenger\u0026gt;\n \u0026lt;framework:middleware id=\"App\\Middleware\\MyMiddleware\"/\u0026gt;\n \u0026lt;framework:middleware id=\"App\\Middleware\\AnotherMiddleware\"/\u0026gt;\n \u0026lt;framework:bus name=\"messenger.bus.default\" default-middleware=\"false\"/\u0026gt;\n \u0026lt;/framework:messenger\u0026gt;\n \u0026lt;/framework:config\u0026gt;\n \u0026lt;/container\u0026gt;\n\n .. code-block:: php\n\n // config/packages/messenger.php\n $container-\u0026gt;loadFromExtension('framework', [\n 'messenger' =\u0026gt; [\n 'buses' =\u0026gt; [\n 'messenger.bus.default' =\u0026gt; [\n 'middleware' =\u0026gt; [\n 'App\\Middleware\\MyMiddleware',\n 'App\\Middleware\\AnotherMiddleware',\n ],\n 'default_middleware' =\u0026gt; false,\n ],\n ],\n ],\n ]);\n\n\n\u003c/pre\u003e\n\u003cdiv dir=\"auto\"\u003e\n\u003cp dir=\"auto\"\u003eNote\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIf a middleware service is abstract, a different instance of the service will\nbe created per bus.\u003c/p\u003e\n\u003c/div\u003e\n\u003ca name=\"user-content-middleware-for-doctrine\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eMiddleware for Doctrine\u003c/h4\u003e\u003ca id=\"user-content-middleware-for-doctrine\" class=\"anchor\" aria-label=\"Permalink: Middleware for Doctrine\" href=\"#middleware-for-doctrine\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cpre\u003e.. versionadded:: 1.11\n\n The following Doctrine middleware were introduced in DoctrineBundle 1.11.\n\n\u003c/pre\u003e\n\u003cp dir=\"auto\"\u003eIf you use Doctrine in your app, a number of optional middleware exist that you\nmay want to use:\u003c/p\u003e\n\u003cpre\u003e.. configuration-block::\n\n .. code-block:: yaml\n\n # config/packages/messenger.yaml\n framework:\n messenger:\n buses:\n command_bus:\n middleware:\n # each time a message is handled, the Doctrine connection\n # is \"pinged\" and reconnected if it's closed. Useful\n # if your workers run for a long time and the database\n # connection is sometimes lost\n - doctrine_ping_connection\n\n # After handling, the Doctrine connection is closed,\n # which can free up database connections in a worker,\n # instead of keeping them open forever\n - doctrine_close_connection\n\n # wraps all handlers in a single Doctrine transaction\n # handlers do not need to call flush() and an error\n # in any handler will cause a rollback\n - doctrine_transaction\n\n # or pass a different entity manager to any\n #- doctrine_transaction: ['custom']\n\n .. code-block:: xml\n\n \u0026lt;!-- config/packages/messenger.xml --\u0026gt;\n \u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\" ?\u0026gt;\n \u0026lt;container xmlns=\"http://symfony.com/schema/dic/services\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xmlns:framework=\"http://symfony.com/schema/dic/symfony\"\n xsi:schemaLocation=\"http://symfony.com/schema/dic/services\n https://symfony.com/schema/dic/services/services-1.0.xsd\n http://symfony.com/schema/dic/symfony\n https://symfony.com/schema/dic/symfony/symfony-1.0.xsd\"\u0026gt;\n\n \u0026lt;framework:config\u0026gt;\n \u0026lt;framework:messenger\u0026gt;\n \u0026lt;framework:bus name=\"command_bus\"\u0026gt;\n \u0026lt;framework:middleware id=\"doctrine_transaction\"/\u0026gt;\n \u0026lt;framework:middleware id=\"doctrine_ping_connection\"/\u0026gt;\n \u0026lt;framework:middleware id=\"doctrine_close_connection\"/\u0026gt;\n\n \u0026lt;!-- or pass a different entity manager to any --\u0026gt;\n \u0026lt;!--\n \u0026lt;framework:middleware id=\"doctrine_transaction\"\u0026gt;\n \u0026lt;framework:argument\u0026gt;custom\u0026lt;/framework:argument\u0026gt;\n \u0026lt;/framework:middleware\u0026gt;\n --\u0026gt;\n \u0026lt;/framework:bus\u0026gt;\n \u0026lt;/framework:messenger\u0026gt;\n \u0026lt;/framework:config\u0026gt;\n \u0026lt;/container\u0026gt;\n\n .. code-block:: php\n\n // config/packages/messenger.php\n $container-\u0026gt;loadFromExtension('framework', [\n 'messenger' =\u0026gt; [\n 'buses' =\u0026gt; [\n 'command_bus' =\u0026gt; [\n 'middleware' =\u0026gt; [\n 'doctrine_transaction',\n 'doctrine_ping_connection',\n 'doctrine_close_connection',\n // Using another entity manager\n ['id' =\u0026gt; 'doctrine_transaction', 'arguments' =\u0026gt; ['custom']],\n ],\n ],\n ],\n ],\n ]);\n\n\u003c/pre\u003e\n\u003ca name=\"user-content-messenger-events\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eMessenger Events\u003c/h4\u003e\u003ca id=\"user-content-messenger-events\" class=\"anchor\" aria-label=\"Permalink: Messenger Events\" href=\"#messenger-events\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIn addition to middleware, Messenger also dispatches several events. You can\n\u003ca href=\"#id53\"\u003e\u003cspan id=\"user-content-id54\"\u003e:doc:`create an event listener \u0026lt;/event_dispatcher\u0026gt;`\u003c/span\u003e\u003c/a\u003e to hook into various parts\nof the process. For each, the event class is the event name:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ca href=\"#id55\"\u003e\u003cspan id=\"user-content-id56\"\u003e:class:`Symfony\\\\Component\\\\Messenger\\\\Event\\\\SendMessageToTransportsEvent`\u003c/span\u003e\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#id57\"\u003e\u003cspan id=\"user-content-id58\"\u003e:class:`Symfony\\\\Component\\\\Messenger\\\\Event\\\\WorkerMessageFailedEvent`\u003c/span\u003e\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#id59\"\u003e\u003cspan id=\"user-content-id60\"\u003e:class:`Symfony\\\\Component\\\\Messenger\\\\Event\\\\WorkerMessageHandledEvent`\u003c/span\u003e\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#id61\"\u003e\u003cspan id=\"user-content-id62\"\u003e:class:`Symfony\\\\Component\\\\Messenger\\\\Event\\\\WorkerMessageReceivedEvent`\u003c/span\u003e\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#id63\"\u003e\u003cspan id=\"user-content-id64\"\u003e:class:`Symfony\\\\Component\\\\Messenger\\\\Event\\\\WorkerStoppedEvent`\u003c/span\u003e\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ca name=\"user-content-multiple-buses-command-event-buses\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eMultiple Buses, Command \u0026amp; Event Buses\u003c/h3\u003e\u003ca id=\"user-content-multiple-buses-command--event-buses\" class=\"anchor\" aria-label=\"Permalink: Multiple Buses, Command \u0026amp; Event Buses\" href=\"#multiple-buses-command--event-buses\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eMessenger gives you a single message bus service by default. But, you can configure\nas many as you want, creating \"command\", \"query\" or \"event\" buses and controlling\ntheir middleware. See \u003ca href=\"#id65\"\u003e\u003cspan id=\"user-content-id66\"\u003e:doc:`/messenger/multiple_buses`\u003c/span\u003e\u003c/a\u003e.\u003c/p\u003e\n\u003ca name=\"user-content-learn-more\"\u003e\u003c/a\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eLearn more\u003c/h3\u003e\u003ca id=\"user-content-learn-more\" class=\"anchor\" aria-label=\"Permalink: Learn more\" href=\"#learn-more\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cpre\u003e.. toctree::\n :maxdepth: 1\n :glob:\n\n /messenger/*\n\n\u003c/pre\u003e\n\n\u003c/article\u003e","renderedFileInfo":null,"shortPath":null,"symbolsEnabled":true,"tabSize":4,"topBannersInfo":{"overridingGlobalFundingFile":false,"globalPreferredFundingPath":"/symfony/.github/blob/6f2ca452c856184a28812bb364b4e34ed50309da/FUNDING.yml","showInvalidCitationWarning":false,"citationHelpUrl":"https://docs.github.com/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-citation-files","actionsOnboardingTip":null},"truncated":false,"viewable":true,"workflowRedirectUrl":null,"symbols":{"timed_out":false,"not_analyzed":true,"symbols":[]}},"copilotInfo":null,"copilotAccessAllowed":false,"modelsAccessAllowed":false,"modelsRepoIntegrationEnabled":false,"csrf_tokens":{"/symfony/symfony-docs/branches":{"post":"HA7LJHR6t4kFUnsbsBrIdpUnzB20XojuLTdnOLiZgoSAy8t_AXJjbLwEerYj79DXVcKtPYmIZVm8n6Vg5LTq5A"},"/repos/preferences":{"post":"DFZMvoyJmybGjLhja-wYzKisRXrzUPxdomQdcH7kDg8LGxXujVaGkofxjszsEHUePp0Jk4ELMpzn8MCEPP8alg"}}},"title":"symfony-docs/messenger.rst at 4.3 · symfony/symfony-docs","appPayload":{"helpUrl":"https://docs.github.com","findFileWorkerPath":"/assets-cdn/worker/find-file-worker-7d7eb7c71814.js","findInFileWorkerPath":"/assets-cdn/worker/find-in-file-worker-1ae9fa256942.js","githubDevUrl":null,"enabled_features":{"code_nav_ui_events":false,"react_blob_overlay":false,"accessible_code_button":true,"github_models_repo_integration":false}}}
0