|
| 1 | +--- |
| 2 | +description: Use Ibexa Messenger to run processes in the background and conserve system resources. |
| 3 | +month_change: true |
| 4 | +--- |
| 5 | + |
| 6 | +# Background tasks |
| 7 | + |
| 8 | +Some operations in [[= product_name =]] don’t have to run immediately when a user clicks a button, for example, re-indexing product prices or processing bulk data. |
| 9 | +Running such operations in real time could slow down the system and disrupt the user experience. |
| 10 | + |
| 11 | +To solve this, [[= product_name =]] provides a package called [[= product_name_base =]] Messenger, which is an overlay to [Symfony Messenger](https://symfony.com/doc/current/messenger.html), and it's job is to queue tasks and run them in the background. |
| 12 | +[[= product_name =]] sends messages (or commands) that represent the work tto be done later. |
| 13 | +These messages are stored in a queue and picked up by a background worker, which ensures that resource-heavy tasks are executed at a convenient time, without putting excessive load on the system. |
| 14 | + |
| 15 | +[[= product_name_base =]] Messenger supports multiple storage backends, such as Doctrine, Redis, and PostgreSQL, and gives developers the flexibility to create their own message handlers for custom use cases. |
| 16 | + |
| 17 | +## How it works |
| 18 | + |
| 19 | +[[= product_name_base =]] Messenger uses a command bus as a queue that stores messages, or commands, which tell the system what you want to happen, and separates them from the handler, which is the code that actually performs the task. |
| 20 | + |
| 21 | +The process works as follows: |
| 22 | + |
| 23 | +1. A message PHP object is dispatched, for example, `ProductPriceReindex`. |
| 24 | +2. The message is wrapped in an envelope, which may contain additional metadata, called stamps, for example, `DeduplicateStamp`. |
| 25 | +3. The message is placed in the transport queue. |
| 26 | +It can be a Doctrine table, a Redis queue, and so on. |
| 27 | +4. A worker process ontinuously reads messages from the queue, pulls them into the default bus `ibexa.messenger.bus` and assigns them to the right haandler. |
| 28 | +5. Handler service processes the message (executes the command). |
| 29 | +You can register multiple handlers for different jobs. |
| 30 | + |
| 31 | +Here is an example of how you can extend your code and use [[= product_name_base =]] Messenger to process your tasks: |
| 32 | + |
| 33 | +### Configure package |
| 34 | + |
| 35 | +Create a config file, for example, `config/packages/ibexa_messenger.yaml` and define your transport: |
| 36 | + |
| 37 | +``` yaml |
| 38 | +ibexa_messenger: |
| 39 | + |
| 40 | + # The DSN of the transport, as expected by Symfony Messenger transport factory. |
| 41 | + transport_dsn: 'doctrine://default?table_name=ibexa_messenger_messages&auto_setup=false' |
| 42 | + deduplication_lock_storage: |
| 43 | + enabled: true |
| 44 | + |
| 45 | + # Doctrine DBAL primary connection or custom service |
| 46 | + type: doctrine # One of "doctrine"; "custom"; "service" |
| 47 | + |
| 48 | + # The service ID of a custom Lock Store, if "service" type is selected |
| 49 | + service: null |
| 50 | + |
| 51 | + # The DSN of the lock store, if "custom" type is selected |
| 52 | + dsn: null |
| 53 | +``` |
| 54 | +
|
| 55 | +!!! note "Supported transports" |
| 56 | +
|
| 57 | + You can define different transports, such as Redis or PostgeSQL. |
| 58 | + For more information, see [Symfony Messenger documentation](https://symfony.com/doc/current/messenger.html#transports-async-queued-messages) or [Symfony Messenger tutorial](https://symfonycasts.com/screencast/messenger/install#installing-messenger). |
| 59 | +
|
| 60 | +### Start worker |
| 61 | +
|
| 62 | +Use a process manager of your choice to run the following command, or make it start together with the server: |
| 63 | +
|
| 64 | +``` bash |
| 65 | +php bin/console messenger:consume ibexa.messenger.transport --bus=ibexa.messenger.bus --siteaccess=<OPTIONAL>` |
| 66 | +``` |
| 67 | + |
| 68 | +In multi-repository setups, the worker process always works for a repository that you indicate by using the `--siteaccess` option, therefore you may need to run multiple workers, one for each SiteAccess. |
| 69 | + |
| 70 | +!!! warning "Multi-repository setups" |
| 71 | + |
| 72 | + Doctrine transport works across multiple repositories without issues, but other transports may need to be adjusted, so that queues across different repositories are not accidentally shared. |
| 73 | + |
| 74 | +### Dispatch message |
| 75 | + |
| 76 | +``` php |
| 77 | +use Symfony\Component\Messenger\MessageBusInterface; |
| 78 | + |
| 79 | +final SomeClassThatSchedulesExecutionInTheBackground |
| 80 | +{ |
| 81 | + public function __construct( |
| 82 | + // Service: "ibexa.messenger.bus" |
| 83 | + MessageBusInterface $bus |
| 84 | + ) |
| 85 | + |
| 86 | + public function schedule(object $message): void |
| 87 | + { |
| 88 | + // Dispatch directly. Message is wrapped with envelope without any stamps. |
| 89 | + $this->bus->dispatch($message); |
| 90 | + |
| 91 | + // Alternatively, wrap with stamps. In this case, DeduplicateStamp ensures |
| 92 | + // that if similar command exists in the queue (or is being processed) |
| 93 | + // it will not be queued again. |
| 94 | + $envelope = Envelope::wrap( |
| 95 | + $message, |
| 96 | + [new DeduplicateStamp('command-name-1'), |
| 97 | + ]); |
| 98 | + |
| 99 | + $this->bus->dispatch($envelope); |
| 100 | + } |
| 101 | +} |
| 102 | +``` |
| 103 | + |
| 104 | +### Register handler |
| 105 | + |
| 106 | +Create the handler class: |
| 107 | + |
| 108 | +``` php |
| 109 | +use Symfony\Component\Messenger\Handler\MessageHandlerInterface; |
| 110 | + |
| 111 | +final class SomeHandler implements MessageHandlerInterface |
| 112 | +{ |
| 113 | + public function __invoke(SomeMessage $message): void |
| 114 | + { |
| 115 | + // Handle message. |
| 116 | + return; |
| 117 | + } |
| 118 | +} |
| 119 | +``` |
| 120 | + |
| 121 | +Add a service definition to `config/services.yaml`: |
| 122 | + |
| 123 | +``` yaml |
| 124 | +services: |
| 125 | + Ibexa\Bundle\Foo\Message\SomeHandler: |
| 126 | + tags: |
| 127 | + - name: messenger.message_handler |
| 128 | + bus: ibexa.messenger.bus |
| 129 | +``` |
0 commit comments