Background tasks¶
Some operations in Ibexa DXP don’t have to run immediately when a user clicks a button, for example, re-indexing product prices or processing bulk data. Running such operations in real time could slow down the system and disrupt the user experience.
To solve this, Ibexa DXP provides a package called Ibexa Messenger, which is an overlay to Symfony Messenger, and it's job is to queue tasks and run them in the background. Ibexa DXP sends messages (or commands) that represent the work to be done later. 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.
Ibexa Messenger supports multiple storage backends, such as Doctrine, Redis/Valkey, and PostgreSQL, and gives developers the flexibility to create their own message handlers for custom use cases.
How it works¶
Ibexa 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.
The process works as follows:
- A message PHP object is dispatched, for example,
ProductPriceReindex. - The message is wrapped in an envelope, which may contain additional metadata, called stamps.
- The message is placed in the transport queue. It can be a Doctrine table, a Redis/Valkey queue, and so on.
- A worker process continuously reads messages from the queue, pulls them into the default bus
ibexa.messenger.busand assigns them to the right handler. - A handler service processes the message (executes the command). You can register multiple handlers for different jobs.
Here is an example of how you can extend your code and use Ibexa Messenger to process your tasks:
Configure package¶
Create a config file, for example, config/packages/ibexa_messenger.yaml and define your transport:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
Supported transports
You can define different transports: Ibexa Messenger has been tested to work with Redis, MySQL, PostgreSQL. For more information, see Symfony Messenger documentation or Symfony Messenger tutorial.
Start worker¶
Use a process manager of your choice to run the following command, or make it start together with the server:
1 | |
In multi-repository setups, the worker process always works for a SiteAccess that you indicate by using the --siteaccess option, therefore you may need to run multiple workers, one for each SiteAccess.
Multi-repository setups
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.
Configure for production environment¶
In production, make sure that Ibexa Messenger keeps running. You can configure a process manager, such as Supervisor or systemd, to restart the worker if it stops.
To prevent issues with memory leaks or stale processes, run the worker with execution limits:
--limitlimits the number of messages the worker processes before exiting.--time-limitlimits the execution time in seconds before the worker exits.--memory-limitrestricts the maximum memory usage.
The following example shows how you can specify these limits:
1 | |
For more information, see Symfony production recommendation for the Messenger component.
If you deploy your application on Ibexa Cloud, using Workers is recommended.
Dispatch message¶
To have a task processed in the background, dispatch an appropriate message by using the \Symfony\Component\Messenger\MessageBusInterfac\MessageBusInterface::dispatch() method, exactly as described in Symfony Messenger documentation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
Additionally, attach message metadata by using stamps.
Stamps¶
You can attach Stamps to a message envelope to add additional metadata and control how the message is processed.
Use Stamps available in Symfony, and combine them with the ones provided by Ibexa DXP:
SudoStamp¶
SudoStamp causes the handler to use sudo mode, bypassing all permission checks when processing the message.
It's automatically attached to every dispatched message.
Caution
Starting with Ibexa DXP 5.0.9, the behavior of automatically attaching a SudoStamp to every message is deprecated and will be removed in 6.0.
For messages that should be processed without taking permissions into account, always attach the SudoStamp manually to keep your code forward-compatible.
The following example shows how you can attach the SudoStamp to the message:
1 2 3 4 | |
UserPermissionStamp¶
UserPermissionStamp allows you to set the repository user to process the message.
When the user is set, handlers execute actions on their behalf and take their permissions into account.
If you don't attach this stamp, the messages are processed by the default repository user called anonymous user.
By combing this stamp with SudoStamp, you can set the repository user and skip the permission checks at the same time.
The following example shows how you can use UserPermissionStamp to preserve the current repository user after the message is dispatched.
1 2 3 4 5 6 | |
Extend Ibexa Messenger¶
Register custom message and handler¶
To handle additional use cases with background tasks, you can create custom message and handler class:
1 2 3 4 5 6 7 8 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Add a service definition to config/services.yaml and set the bus to ibexa.messenger.bus:
1 2 3 4 5 | |