From 274c96a64038664b796f0cbb857f6f4d7c958890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Noco=C5=84?= Date: Fri, 3 Jul 2026 12:24:55 +0200 Subject: [PATCH 1/3] Described stamps for Ibexa Messenger --- ...sThatSchedulesExecutionInTheBackground.php | 24 +++--- deptrac.baseline.yaml | 2 - .../background_tasks.md | 74 +++++++++++++++++-- 3 files changed, 76 insertions(+), 24 deletions(-) diff --git a/code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php b/code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php index 41edfb4610..4219f12664 100644 --- a/code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php +++ b/code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php @@ -2,29 +2,25 @@ namespace App\Dispatcher; -use Ibexa\Bundle\Messenger\Stamp\DeduplicateStamp; -use Symfony\Component\Messenger\Envelope; +use Ibexa\Contracts\Core\Repository\PermissionResolver; +use Ibexa\Contracts\Messenger\Stamp\SudoStamp; +use Ibexa\Contracts\Messenger\Stamp\UserPermissionStamp; use Symfony\Component\Messenger\MessageBusInterface; final readonly class SomeClassThatSchedulesExecutionInTheBackground { - public function __construct(private MessageBusInterface $bus) - { + public function __construct( + private MessageBusInterface $bus, + private PermissionResolver $permissionResolver, + ) { } public function schedule(object $message): void { - // Dispatch directly. Message is wrapped with envelope without any stamps. $this->bus->dispatch($message); - // Alternatively, wrap with stamps. In this case, DeduplicateStamp ensures - // that if similar command exists in the queue (or is being processed) - // it will not be queued again. - $envelope = Envelope::wrap( - $message, - [new DeduplicateStamp('command-name-1')] - ); - - $this->bus->dispatch($envelope); + $currentUserId = $this->permissionResolver->getCurrentUserReference()->getUserId(); + $this->bus->dispatch($message, [new UserPermissionStamp($currentUserId)]); + $this->bus->dispatch($message, [new SudoStamp()]); } } diff --git a/deptrac.baseline.yaml b/deptrac.baseline.yaml index 9fef31d4bc..81bf5a8d3b 100644 --- a/deptrac.baseline.yaml +++ b/deptrac.baseline.yaml @@ -115,8 +115,6 @@ deptrac: - Ibexa\Discounts\Value\AbstractDiscountExpressionAware App\Discounts\Rule\PurchasingPowerParityRuleFactory: - Ibexa\Discounts\Repository\DiscountRule\DiscountRuleFactoryInterface - App\Dispatcher\SomeClassThatSchedulesExecutionInTheBackground: - - Ibexa\Bundle\Messenger\Stamp\DeduplicateStamp App\EventListener\TextAnchorMenuTabListener: - Ibexa\AdminUi\Menu\ContentEditAnchorMenuBuilder - Ibexa\AdminUi\Menu\Event\ConfigureMenuEvent diff --git a/docs/infrastructure_and_maintenance/background_tasks.md b/docs/infrastructure_and_maintenance/background_tasks.md index 52c75dd0cc..54d57f5b05 100644 --- a/docs/infrastructure_and_maintenance/background_tasks.md +++ b/docs/infrastructure_and_maintenance/background_tasks.md @@ -21,7 +21,7 @@ These messages are stored in a queue and picked up by a background worker, which The process works as follows: 1. A message PHP object is dispatched, for example, `ProductPriceReindex`. -2. The message is wrapped in an envelope, which may contain additional metadata, called stamps, for example, `DeduplicateStamp`. +2. The message is wrapped in an envelope, which may contain additional metadata, called [stamps](#stamps). 3. The message is placed in the transport queue. It can be a Doctrine table, a Redis/Valkey queue, and so on. 4. A worker process continuously reads messages from the queue, pulls them into the default bus `ibexa.messenger.bus` and assigns them to the right handler. @@ -92,25 +92,83 @@ For more information, see [Symfony production recommendation for the Messenger c If you deploy your application on [[= product_name_cloud =]], using [Workers](https://fixed.docs.upsun.com/guides/symfony/workers.html) is recommended. -### Dispatch message +## Dispatch message -Dispatch a message from your code like in the following example: +To have a task processed in the background, dispatch an appriopriate message by using the `\Symfony\Component\Messenger\MessageBusInterfac\MessageBusInterface::dispatch()` method, exactly as described in [Symfony Messenger documentation]([[= symfony_doc =]]/messenger.html#dispatching-the-message): ``` php -[[= include_code("code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php") =]] +[[= include_code('code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php', 1, 3) =]] + +[[= include_code('code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php', 8, 13) =]] +[[= include_code('code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php', 15, 20) =]] +[[= include_code('code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php', 25, 26) =]] ``` -### Register handler +Additionally, attach message metada by using [stamps](#stamps). + +### Stamps + +You can attach [Stamps]([[= symfony_doc =]]/messenger.html#envelopes-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 [[= product_name =]]: + +- [SudoStamp](#sudostamp) +- [UserPermissionStamp](#userpermissionstamp) + +#### SudoStamp + +[`SudoStamp`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Messenger-Stamp-SudoStamp.html) causes the handler to [use sudo mode](php_api.md#using-sudo), bypassing all permission checks when processing the message. + +It's automatically attached to every dispatched message. -Create the handler class: +!!! 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: + +``` php +[[= include_code('code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php', 6, 6, remove_indent=True) =]] +[[= include_code('code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php', 8, 9, remove_indent=True) =]] + +[[= include_code('code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php', 24, 24, remove_indent=True) =]] +``` + +#### UserPermissionStamp + +[`UserPermissionStamp`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Messenger-Stamp-UserPermissionStamp.html) allows you to [set the repository user](php_api.md#setting-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`](#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. + +``` php +[[= include_code('code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php', 5, 5, remove_indent=True) =]] +[[= include_code('code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php', 7, 9, remove_indent=True) =]] + +[[= include_code('code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php', 22, 23, remove_indent=True) =]] +``` + +## Extend Ibexa Messenger + +### Register custom message and handler + +To handle additional use cases with background tasks, you can create [custom message and handler class]([[= symfony_doc =]]/messenger.html#creating-a-message-handler): + +``` php +[[= include_code('code_samples/background_tasks/src/Message/SomeMessage.php') =]] +``` ``` php [[= include_code("code_samples/background_tasks/src/MessageHandler/SomeHandler.php") =]] ``` -Add a service definition to `config/services.yaml`: +Add a service definition to `config/services.yaml` and set the `bus` to `ibexa.messenger.bus`: -``` yaml +``` yaml hl_lines="4-5" services: App\MessageHandler\SomeHandler: tags: From 31f157fccfd216b4305dae9472a95c3927129877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Noco=C5=84?= Date: Fri, 3 Jul 2026 14:56:02 +0200 Subject: [PATCH 2/3] Fixed typos --- docs/content_management/data_migration/importing_data.md | 2 +- docs/infrastructure_and_maintenance/background_tasks.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/content_management/data_migration/importing_data.md b/docs/content_management/data_migration/importing_data.md index 0c01a46bc9..a472d500e4 100644 --- a/docs/content_management/data_migration/importing_data.md +++ b/docs/content_management/data_migration/importing_data.md @@ -88,7 +88,7 @@ You can run a set of one or more similar migration steps multiple times by using A repeatable migration performs the defined migration steps as many times as specified: -- with an [interation counter](#repeatable-steps-with-iteration-counter), mimicking the behavior of a [`for` loop](https://www.php.net/manual/en/control-structures.for.php) +- with an [iteration counter](#repeatable-steps-with-iteration-counter), mimicking the behavior of a [`for` loop](https://www.php.net/manual/en/control-structures.for.php) - with a [list of items](#repeatable-steps-with-items), mimicking the behavior of a [`foreach` loop](https://www.php.net/manual/en/control-structures.foreach.php) !!! tip diff --git a/docs/infrastructure_and_maintenance/background_tasks.md b/docs/infrastructure_and_maintenance/background_tasks.md index 54d57f5b05..c850cfea95 100644 --- a/docs/infrastructure_and_maintenance/background_tasks.md +++ b/docs/infrastructure_and_maintenance/background_tasks.md @@ -94,7 +94,7 @@ If you deploy your application on [[= product_name_cloud =]], using [Workers](ht ## Dispatch message -To have a task processed in the background, dispatch an appriopriate message by using the `\Symfony\Component\Messenger\MessageBusInterfac\MessageBusInterface::dispatch()` method, exactly as described in [Symfony Messenger documentation]([[= symfony_doc =]]/messenger.html#dispatching-the-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]([[= symfony_doc =]]/messenger.html#dispatching-the-message): ``` php [[= include_code('code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php', 1, 3) =]] @@ -104,7 +104,7 @@ To have a task processed in the background, dispatch an appriopriate message by [[= include_code('code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php', 25, 26) =]] ``` -Additionally, attach message metada by using [stamps](#stamps). +Additionally, attach message metadata by using [stamps](#stamps). ### Stamps From 68073579a0d15058f5be20de0357afd50e9948c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Noco=C5=84?= Date: Fri, 10 Jul 2026 10:38:25 +0200 Subject: [PATCH 3/3] Link to Symfony messages --- docs/infrastructure_and_maintenance/background_tasks.md | 2 +- mkdocs.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/infrastructure_and_maintenance/background_tasks.md b/docs/infrastructure_and_maintenance/background_tasks.md index c850cfea95..bf7f2c32cc 100644 --- a/docs/infrastructure_and_maintenance/background_tasks.md +++ b/docs/infrastructure_and_maintenance/background_tasks.md @@ -110,7 +110,7 @@ Additionally, attach message metadata by using [stamps](#stamps). You can attach [Stamps]([[= symfony_doc =]]/messenger.html#envelopes-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 [[= product_name =]]: +Use [Stamps available in Symfony](https://github.com/symfony/symfony/tree/[[= symfony_version =]]/src/Symfony/Component/Messenger/Stamp), and combine them with the ones provided by [[= product_name =]]: - [SudoStamp](#sudostamp) - [UserPermissionStamp](#userpermissionstamp) diff --git a/mkdocs.yml b/mkdocs.yml index aa8294e9bb..9a9d01ad3f 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1042,6 +1042,7 @@ extra: latest_tag_4_6: '4.6.31' latest_tag_5_0: '5.0.9' + symfony_version: '7.4' symfony_doc: 'https://symfony.com/doc/7.4' user_doc: 'https://doc.ibexa.co/projects/userguide/en/5.0' connect_doc: 'https://doc.ibexa.co/projects/connect/en/latest'