From 59d3a0d652e250ffe96557802c93cd39c328177d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20D=C4=85browski?= <64841871+dabrt@users.noreply.github.com> Date: Fri, 19 Sep 2025 21:00:09 +0200 Subject: [PATCH 01/15] API changes documented --- docs/api/event_reference/discounts_events.md | 2 ++ .../discounts_search_reference/discounts_criteria.md | 12 +++++++----- .../discounts_sort_clauses.md | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/api/event_reference/discounts_events.md b/docs/api/event_reference/discounts_events.md index 302a6b7b9d..235b936134 100644 --- a/docs/api/event_reference/discounts_events.md +++ b/docs/api/event_reference/discounts_events.md @@ -16,6 +16,8 @@ The events below are dispatched when managing [discounts](discounts_guide.md): |---|---| |[BeforeCreateDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeCreateDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | |[CreateDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-CreateDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | +|[BeforeEnableDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeEnableDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | +|[EnableDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-EnableDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | |[BeforeDeleteDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeDeleteDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | |[DeleteDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-DeleteDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | |[BeforeUpdateDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeUpdateDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html)| diff --git a/docs/search/discounts_search_reference/discounts_criteria.md b/docs/search/discounts_search_reference/discounts_criteria.md index 6ca525ca6a..ac4102e9da 100644 --- a/docs/search/discounts_search_reference/discounts_criteria.md +++ b/docs/search/discounts_search_reference/discounts_criteria.md @@ -10,17 +10,19 @@ Search Criteria are found in the `Ibexa\Contracts\Discounts\Value\Query\Criterio | Criterion | Description | |---|---| -| [CreatedAtCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-CreatedAtCriterion.html) | Find discounts with given creation date| -| [CreatorCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-CreatorCriterion.html) | Find discounts created by specific users| +| [CreatedAtCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-CreatedAtCriterion.html) | Find discounts with given creation date | +| [CreatorCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-CreatorCriterion.html) | Find discounts created by specific users | | [EndDateCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-EndDateCriterion.html) | Find discounts by their end date. For permanent discounts, the end date is set to `null` | +| [IndexedAtCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-IndexedAtCriterion.html) | Find discounts based on the date and time when they were indexed | | [IdentifierCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-IdentifierCriterion.html) | Find discounts by their identifier | -| [IsEnabledCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-IsEnabledCriterion.html) | Find discounts by their status| +| [IsEnabledCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-IsEnabledCriterion.html) | Find discounts by their status | | [LogicalAnd](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-LogicalAnd.html) | Composite criterion to group multiple criterions using the AND condition | | [LogicalOr](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-LogicalOr.html) | Composite criterion to group multiple criterions using the OR condition | | [NameCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-NameCriterion.html) | Find discounts by their name | | [PriorityCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-PriorityCriterion.html) | Find discounts by their priority | -| [StartDateCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-StartDateCriterion.html) | Find discounts with given start date| -| [TypeCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-TypeCriterion.html) | Find cart or catalog discounts by using constants from the [DiscountType](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-DiscountType.html) class| +| [StartDateCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-StartDateCriterion.html) | Find discounts with given start date | +| [TypeCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-TypeCriterion.html) | Find cart or catalog discounts by using constants from the [DiscountType](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-DiscountType.html) class | +| [UpdatedAtCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-UpdatedAtCriterion.html) | Find discounts based on the date and time when they were indexed | You can use the [FieldValueCriterion's constants](/api/php_api/php_api_reference/classes/Ibexa-Contracts-CoreSearch-Values-Query-Criterion-FieldValueCriterion.html#constants) like `FieldValueCriterion::COMPARISON_CONTAINS` or `FieldValueCriterion::COMPARISON_STARTS_WITH` to specify the operator for the condition. diff --git a/docs/search/discounts_search_reference/discounts_sort_clauses.md b/docs/search/discounts_search_reference/discounts_sort_clauses.md index 7b0ee81f64..b2d4432bbc 100644 --- a/docs/search/discounts_search_reference/discounts_sort_clauses.md +++ b/docs/search/discounts_search_reference/discounts_sort_clauses.md @@ -14,6 +14,7 @@ Sort Clauses are found in the [`Ibexa\Contracts\Discounts\Value\Query\SortClause | [EndDate](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-SortClause-EndDate.html)| Sort by discount's end date | | [Id](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-SortClause-Id.html)| Sort by discount's database ID | | [Identifier](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-SortClause-Identifier.html)| Sort by discount identifier | +| [OverridePrioritization](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-SortClause-OverridePrioritization.html)| Sort prioritizing discounts with discount code over automatic ones | | [Priority](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-SortClause-Priority.html)| Sort by discount priority | | [StartDate](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-SortClause-StartDate.html)| Sort by discount start date | | [Type](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-SortClause-Type.html)| Sort by the place where the discount activates: catalog or cart. When sorting with ascending order, cart discounts are returned first. | From d812b76b33e8768e9d24373f4dd0652b7662f18e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20D=C4=85browski?= <64841871+dabrt@users.noreply.github.com> Date: Sat, 20 Sep 2025 04:34:13 +0200 Subject: [PATCH 02/15] Add messenger description --- .../background_tasks.md | 129 ++++++++++++++++++ .../infrastructure_and_maintenance.md | 1 + mkdocs.yml | 1 + 3 files changed, 131 insertions(+) create mode 100644 docs/infrastructure_and_maintenance/background_tasks.md diff --git a/docs/infrastructure_and_maintenance/background_tasks.md b/docs/infrastructure_and_maintenance/background_tasks.md new file mode 100644 index 0000000000..75c2394140 --- /dev/null +++ b/docs/infrastructure_and_maintenance/background_tasks.md @@ -0,0 +1,129 @@ +--- +description: Use Ibexa Messenger to run processes in the background and conserve system resources. +month_change: true +--- + +# Background tasks + +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. +Running such operations in real time could slow down the system and disrupt the user experience. + +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. +[[= product_name =]] sends messages (or commands) that represent the work tto 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. + +[[= 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. + +## How it works + +[[= 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. + +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`. +3. The message is placed in the transport queue. +It can be a Doctrine table, a Redis queue, and so on. +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. +5. 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 [[= product_name_base =]] Messenger to process your tasks: + +### Configure package + +Create a config file, for example, `config/packages/ibexa_messenger.yaml` and define your transport: + +``` yaml +ibexa_messenger: + + # The DSN of the transport, as expected by Symfony Messenger transport factory. + transport_dsn: 'doctrine://default?table_name=ibexa_messenger_messages&auto_setup=false' + deduplication_lock_storage: + enabled: true + + # Doctrine DBAL primary connection or custom service + type: doctrine # One of "doctrine"; "custom"; "service" + + # The service ID of a custom Lock Store, if "service" type is selected + service: null + + # The DSN of the lock store, if "custom" type is selected + dsn: null +``` + +!!! note "Supported transports" + + You can define different transports, such as Redis or PostgeSQL. + 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). + +### Start worker + +Use a process manager of your choice to run the following command, or make it start together with the server: + +``` bash +php bin/console messenger:consume ibexa.messenger.transport --bus=ibexa.messenger.bus --siteaccess=` +``` + +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. + +!!! warning "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. + +### Dispatch message + +``` php +use Symfony\Component\Messenger\MessageBusInterface; + +final SomeClassThatSchedulesExecutionInTheBackground +{ + public function __construct( + // Service: "ibexa.messenger.bus" + MessageBusInterface $bus + ) + + 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); + } +} +``` + +### Register handler + +Create the handler class: + +``` php +use Symfony\Component\Messenger\Handler\MessageHandlerInterface; + +final class SomeHandler implements MessageHandlerInterface +{ + public function __invoke(SomeMessage $message): void + { + // Handle message. + return; + } +} +``` + +Add a service definition to `config/services.yaml`: + +``` yaml +services: + Ibexa\Bundle\Foo\Message\SomeHandler: + tags: + - name: messenger.message_handler + bus: ibexa.messenger.bus +``` diff --git a/docs/infrastructure_and_maintenance/infrastructure_and_maintenance.md b/docs/infrastructure_and_maintenance/infrastructure_and_maintenance.md index e78c231344..d4b263d23b 100644 --- a/docs/infrastructure_and_maintenance/infrastructure_and_maintenance.md +++ b/docs/infrastructure_and_maintenance/infrastructure_and_maintenance.md @@ -9,6 +9,7 @@ page_type: landing_page "infrastructure_and_maintenance/cache/cache", "infrastructure_and_maintenance/clustering/clustering", "infrastructure_and_maintenance/performance", + "infrastructure_and_maintenance/background_tasks", "infrastructure_and_maintenance/databases", "infrastructure_and_maintenance/environments", "infrastructure_and_maintenance/support_and_maintenance_faq", diff --git a/mkdocs.yml b/mkdocs.yml index 89b6ff2ecc..eaf33d6eda 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -814,6 +814,7 @@ nav: - DevOps: infrastructure_and_maintenance/devops.md - Backup: infrastructure_and_maintenance/backup.md - Performance: infrastructure_and_maintenance/performance.md + - Background tasks: infrastructure_and_maintenance/background_tasks.md - Environments: infrastructure_and_maintenance/environments.md - Sessions: infrastructure_and_maintenance/sessions.md - Logging: infrastructure_and_maintenance/logging.md From 302bd076d1f56ee738344e1b4c970cf2d683fff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20D=C4=85browski?= <64841871+dabrt@users.noreply.github.com> Date: Sat, 20 Sep 2025 05:09:53 +0200 Subject: [PATCH 03/15] Modify configure_discounts.md --- docs/discounts/configure_discounts.md | 25 +++++++++++++++++++++++++ docs/discounts/discounts_guide.md | 9 +++++++++ 2 files changed, 34 insertions(+) diff --git a/docs/discounts/configure_discounts.md b/docs/discounts/configure_discounts.md index 46c6e2ab77..ba3ce6abeb 100644 --- a/docs/discounts/configure_discounts.md +++ b/docs/discounts/configure_discounts.md @@ -30,6 +30,31 @@ ibexa: products_list_per_page_limit: 15 ``` +## Discount re-indexing + +Discounts feature uses [[= product_name_base =]] Messenger to reindex discounts and product prices in the background. +This way changes are processed efficiently without slowing down the system and disrupting the user experience. + +When triggered periodically, the `ibexa:discounts:reindex` command identifies discounts that require re-indexing, ensuring catalog prices always remain up-to-date. +If there are edits to discounts that should result in changed product catalog prices, messages are dispatched to an [[= product_name_base =]] Messenger queue and consumed by a background worker. +The worker passes the messages to the handler, which then starts the re-indexing process at the most convenient moment. + +To use discount re-indexing in the background: + +1\. Make sure that the transport layer is [defined properly](background_tasks.md#configure-package) in Messenger configuration. + +2\. Make sure that the worker starts together with the application to watch the transport bus: + +``` bash +php bin/console messenger:consume ibexa.messenger.transport --bus=ibexa.messenger.bus +``` + +3\. Use a scheduler of your choice, to periodically run the following command: + +``` bash +php bin/console ibexa:discounts:reindex +``` + ## Rate limiting To prevent malicious actors from trying all the possible discount code combinations using brute-force attacks, the [`/discounts_codes/{cartIdentifier}/apply` endpoint](/api/rest_api/rest_api_reference/rest_api_reference.html#discount-codes-apply-discount-to-cart) is rate limited using the [Rate Limiter Symfony component]([[= symfony_doc =]]/rate_limiter.html). diff --git a/docs/discounts/discounts_guide.md b/docs/discounts/discounts_guide.md index eae3c4b581..5e607e8c52 100644 --- a/docs/discounts/discounts_guide.md +++ b/docs/discounts/discounts_guide.md @@ -113,6 +113,15 @@ You can also limit the usage per customer: - limited use: every customer can use the code a specified number of times - unlimited +### Discount re-indexing + +Discounts affect the prices shown in the product catalog. +When a discount is created, updated, or expires, the product catalog must be re-indexed to ensure that search results and product listings display the correct price. + +To prevent performance disruptions which could occur if re-indexing occurred immediately, [[= product_name =]] uses the [Ibexa Messenger](background_tasks.md)'s background queue to process re-indexing tasks in the background. + +By [configuring the process](configure_discounts.md#discount-re-indexing), you can decide when is the most convenient time to perform re-indexing and improve your application's overall stability. + ## Capabilities ### Management From cc7267e79f648ac0694ff5296033598909f972e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20D=C4=85browski?= <64841871+dabrt@users.noreply.github.com> Date: Sat, 20 Sep 2025 05:21:17 +0200 Subject: [PATCH 04/15] Typos fix --- docs/discounts/configure_discounts.md | 4 ++-- docs/discounts/discounts_guide.md | 2 +- docs/infrastructure_and_maintenance/background_tasks.md | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/discounts/configure_discounts.md b/docs/discounts/configure_discounts.md index ba3ce6abeb..c0b7ba6097 100644 --- a/docs/discounts/configure_discounts.md +++ b/docs/discounts/configure_discounts.md @@ -36,7 +36,7 @@ Discounts feature uses [[= product_name_base =]] Messenger to reindex discounts This way changes are processed efficiently without slowing down the system and disrupting the user experience. When triggered periodically, the `ibexa:discounts:reindex` command identifies discounts that require re-indexing, ensuring catalog prices always remain up-to-date. -If there are edits to discounts that should result in changed product catalog prices, messages are dispatched to an [[= product_name_base =]] Messenger queue and consumed by a background worker. +If there are edits to discounts that should result in changed product catalog prices, messages are dispatched to the [[= product_name_base =]] Messenger's queue and consumed by a background worker. The worker passes the messages to the handler, which then starts the re-indexing process at the most convenient moment. To use discount re-indexing in the background: @@ -49,7 +49,7 @@ To use discount re-indexing in the background: php bin/console messenger:consume ibexa.messenger.transport --bus=ibexa.messenger.bus ``` -3\. Use a scheduler of your choice, to periodically run the following command: +3\. Use a scheduler of your choice to periodically run the following command: ``` bash php bin/console ibexa:discounts:reindex diff --git a/docs/discounts/discounts_guide.md b/docs/discounts/discounts_guide.md index 5e607e8c52..d6a45e38f2 100644 --- a/docs/discounts/discounts_guide.md +++ b/docs/discounts/discounts_guide.md @@ -116,7 +116,7 @@ You can also limit the usage per customer: ### Discount re-indexing Discounts affect the prices shown in the product catalog. -When a discount is created, updated, or expires, the product catalog must be re-indexed to ensure that search results and product listings display the correct price. +When a discount is created, updated, or expires, the product catalog must be re-indexed to ensure that the search results and product listings display correct prices. To prevent performance disruptions which could occur if re-indexing occurred immediately, [[= product_name =]] uses the [Ibexa Messenger](background_tasks.md)'s background queue to process re-indexing tasks in the background. diff --git a/docs/infrastructure_and_maintenance/background_tasks.md b/docs/infrastructure_and_maintenance/background_tasks.md index 75c2394140..66f30db82e 100644 --- a/docs/infrastructure_and_maintenance/background_tasks.md +++ b/docs/infrastructure_and_maintenance/background_tasks.md @@ -24,7 +24,7 @@ The process works as follows: 2. The message is wrapped in an envelope, which may contain additional metadata, called stamps, for example, `DeduplicateStamp`. 3. The message is placed in the transport queue. It can be a Doctrine table, a Redis queue, and so on. -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. +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. 5. Handler service processes the message (executes the command). You can register multiple handlers for different jobs. @@ -54,7 +54,7 @@ ibexa_messenger: !!! note "Supported transports" - You can define different transports, such as Redis or PostgeSQL. + You can define different transports, such as Redis or PostgreSQL. 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). ### Start worker From de5b13c8dc0482b8221b14b1aa76371b1a3e297d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20D=C4=85browski?= <64841871+dabrt@users.noreply.github.com> Date: Sat, 20 Sep 2025 05:32:11 +0200 Subject: [PATCH 05/15] Typos --- docs/discounts/configure_discounts.md | 2 +- docs/discounts/discounts_guide.md | 4 ++-- docs/infrastructure_and_maintenance/background_tasks.md | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/discounts/configure_discounts.md b/docs/discounts/configure_discounts.md index c0b7ba6097..782ed68973 100644 --- a/docs/discounts/configure_discounts.md +++ b/docs/discounts/configure_discounts.md @@ -41,7 +41,7 @@ The worker passes the messages to the handler, which then starts the re-indexing To use discount re-indexing in the background: -1\. Make sure that the transport layer is [defined properly](background_tasks.md#configure-package) in Messenger configuration. +1\. Make sure that the transport layer is [defined properly](background_tasks.md#configure-package) in [[= product_name_base =]] Messenger configuration. 2\. Make sure that the worker starts together with the application to watch the transport bus: diff --git a/docs/discounts/discounts_guide.md b/docs/discounts/discounts_guide.md index d6a45e38f2..99e58c17f9 100644 --- a/docs/discounts/discounts_guide.md +++ b/docs/discounts/discounts_guide.md @@ -118,9 +118,9 @@ You can also limit the usage per customer: Discounts affect the prices shown in the product catalog. When a discount is created, updated, or expires, the product catalog must be re-indexed to ensure that the search results and product listings display correct prices. -To prevent performance disruptions which could occur if re-indexing occurred immediately, [[= product_name =]] uses the [Ibexa Messenger](background_tasks.md)'s background queue to process re-indexing tasks in the background. +To prevent performance disruptions which could occur if re-indexing occurred immediately, [[= product_name =]] uses the [[= product_name_base =]] Messenger's [background queue](background_tasks.md) to process re-indexing tasks in the background. -By [configuring the process](configure_discounts.md#discount-re-indexing), you can decide when is the most convenient time to perform re-indexing and improve your application's overall stability. +By [configuring the process](configure_discounts.md#discount-re-indexing), you ensure that re-indexing is performed at the most convenient time to maintain your application's overall stability. ## Capabilities diff --git a/docs/infrastructure_and_maintenance/background_tasks.md b/docs/infrastructure_and_maintenance/background_tasks.md index 66f30db82e..c62cb22042 100644 --- a/docs/infrastructure_and_maintenance/background_tasks.md +++ b/docs/infrastructure_and_maintenance/background_tasks.md @@ -25,7 +25,7 @@ The process works as follows: 3. The message is placed in the transport queue. It can be a Doctrine table, a Redis 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. -5. Handler service processes the message (executes the command). +5. 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 [[= product_name_base =]] Messenger to process your tasks: @@ -54,7 +54,7 @@ ibexa_messenger: !!! note "Supported transports" - You can define different transports, such as Redis or PostgreSQL. + You can define different transports: [[= product_name_base =]] Messenger has been tested to work with Redis, MySQL, PostgreSQL. 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). ### Start worker From 7539ab73b0c349641a0ea48d35e1f32191f8e27c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20D=C4=85browski?= <64841871+dabrt@users.noreply.github.com> Date: Tue, 30 Sep 2025 12:23:35 +0200 Subject: [PATCH 06/15] Move code to code_samples --- ...sThatSchedulesExecutionInTheBackground.php | 33 ++++++++++++++ .../src/Message/SomeMessage.php | 8 ++++ .../src/MessageHandler/SomeHandler.php | 14 ++++++ docs/discounts/configure_discounts.md | 8 +++- .../background_tasks.md | 43 ++++--------------- 5 files changed, 69 insertions(+), 37 deletions(-) create mode 100644 code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php create mode 100644 code_samples/background_tasks/src/Message/SomeMessage.php create mode 100644 code_samples/background_tasks/src/MessageHandler/SomeHandler.php diff --git a/code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php b/code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php new file mode 100644 index 0000000000..98e3e567c3 --- /dev/null +++ b/code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php @@ -0,0 +1,33 @@ +bus = $bus; + } + + 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); + } +} diff --git a/code_samples/background_tasks/src/Message/SomeMessage.php b/code_samples/background_tasks/src/Message/SomeMessage.php new file mode 100644 index 0000000000..02f994bf4f --- /dev/null +++ b/code_samples/background_tasks/src/Message/SomeMessage.php @@ -0,0 +1,8 @@ +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); - } -} +[[= include_file("code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php") =]] ``` ### Register handler @@ -106,16 +88,7 @@ final SomeClassThatSchedulesExecutionInTheBackground Create the handler class: ``` php -use Symfony\Component\Messenger\Handler\MessageHandlerInterface; - -final class SomeHandler implements MessageHandlerInterface -{ - public function __invoke(SomeMessage $message): void - { - // Handle message. - return; - } -} +[[= include_file("code_samples/background_tasks/src/MessageHandler/SomeHandler.php") =]] ``` Add a service definition to `config/services.yaml`: From abdd2c0d8023fc5c022e9527091f04757e68ca4e Mon Sep 17 00:00:00 2001 From: dabrt Date: Tue, 30 Sep 2025 10:36:25 +0000 Subject: [PATCH 07/15] PHP & JS CS Fixes --- .../SomeClassThatSchedulesExecutionInTheBackground.php | 10 +++++----- .../background_tasks/src/Message/SomeMessage.php | 2 +- .../src/MessageHandler/SomeHandler.php | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php b/code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php index 98e3e567c3..3563654987 100644 --- a/code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php +++ b/code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php @@ -1,10 +1,10 @@ -bus->dispatch($message); - // Alternatively, wrap with stamps. In this case, DeduplicateStamp ensures + // 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, + $message, [new DeduplicateStamp('command-name-1')] ); diff --git a/code_samples/background_tasks/src/Message/SomeMessage.php b/code_samples/background_tasks/src/Message/SomeMessage.php index 02f994bf4f..8f906c23b3 100644 --- a/code_samples/background_tasks/src/Message/SomeMessage.php +++ b/code_samples/background_tasks/src/Message/SomeMessage.php @@ -1,4 +1,4 @@ - Date: Tue, 30 Sep 2025 12:59:50 +0200 Subject: [PATCH 08/15] =?UTF-8?q?Implement=20Pawe=C5=82's=20comments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../background_tasks/src/MessageHandler/SomeHandler.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/code_samples/background_tasks/src/MessageHandler/SomeHandler.php b/code_samples/background_tasks/src/MessageHandler/SomeHandler.php index 8888b6bc97..aa58852f2b 100644 --- a/code_samples/background_tasks/src/MessageHandler/SomeHandler.php +++ b/code_samples/background_tasks/src/MessageHandler/SomeHandler.php @@ -3,9 +3,7 @@ namespace App\MessageHandler; use App\Message\SomeMessage; -use Symfony\Component\Messenger\Handler\MessageHandlerInterface; - -final class SomeHandler implements MessageHandlerInterface +final class SomeHandler { public function __invoke(SomeMessage $message): void { From 56d1deb2abd3b62ae470090173ff8a0df0368406 Mon Sep 17 00:00:00 2001 From: dabrt Date: Tue, 30 Sep 2025 11:15:56 +0000 Subject: [PATCH 09/15] PHP & JS CS Fixes --- code_samples/background_tasks/src/MessageHandler/SomeHandler.php | 1 + 1 file changed, 1 insertion(+) diff --git a/code_samples/background_tasks/src/MessageHandler/SomeHandler.php b/code_samples/background_tasks/src/MessageHandler/SomeHandler.php index 3be4c45f68..2b873a3245 100644 --- a/code_samples/background_tasks/src/MessageHandler/SomeHandler.php +++ b/code_samples/background_tasks/src/MessageHandler/SomeHandler.php @@ -3,6 +3,7 @@ namespace App\MessageHandler; use App\Message\SomeMessage; + final class SomeHandler { public function __invoke(SomeMessage $message): void From d9bd01e6f5e82e13b60ac982f4d45a544bb2b903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20D=C4=85browski?= <64841871+dabrt@users.noreply.github.com> Date: Wed, 1 Oct 2025 09:40:40 +0200 Subject: [PATCH 10/15] Implement reviewer comments --- docs/discounts/configure_discounts.md | 2 +- docs/infrastructure_and_maintenance/background_tasks.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/discounts/configure_discounts.md b/docs/discounts/configure_discounts.md index 6c863294aa..be9bbf54ea 100644 --- a/docs/discounts/configure_discounts.md +++ b/docs/discounts/configure_discounts.md @@ -35,7 +35,7 @@ ibexa: Discounts feature uses [[= product_name_base =]] Messenger to reindex discounts and product prices in the background. This way changes are processed efficiently without slowing down the system and disrupting the user experience. -When triggered periodically, the `ibexa:discounts:reindex` command identifies discounts that require re-indexing, ensuring catalog prices always remain up-to-date. +When triggered periodically, the `ibexa:discounts:reindex` command identifies discounts that require re-indexing, ensuring prices always remain up-to-date. If there are edits to discounts that should result in changed product catalog prices, messages are dispatched to the [[= product_name_base =]] Messenger's queue and consumed by a background worker. The worker passes the messages to the handler, which then starts the re-indexing process at the most convenient moment. diff --git a/docs/infrastructure_and_maintenance/background_tasks.md b/docs/infrastructure_and_maintenance/background_tasks.md index 1d1a0c1176..f9037fd0dd 100644 --- a/docs/infrastructure_and_maintenance/background_tasks.md +++ b/docs/infrastructure_and_maintenance/background_tasks.md @@ -9,7 +9,7 @@ Some operations in [[= product_name =]] don’t have to run immediately when a u Running such operations in real time could slow down the system and disrupt the user experience. 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. -[[= product_name =]] sends messages (or commands) that represent the work tto be done later. +[[= product_name =]] 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. [[= 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. @@ -65,7 +65,7 @@ Use a process manager of your choice to run the following command, or make it st php bin/console messenger:consume ibexa.messenger.transport --bus=ibexa.messenger.bus --siteaccess=` ``` -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. +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. !!! warning "Multi-repository setups" From 3656c15083d3f8d112c97627ee9d96eee1f3622c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20D=C4=85browski?= <64841871+dabrt@users.noreply.github.com> Date: Wed, 1 Oct 2025 15:38:07 +0200 Subject: [PATCH 11/15] Apply suggestions from code review Co-authored-by: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> --- docs/api/event_reference/discounts_events.md | 2 +- docs/discounts/configure_discounts.md | 6 +++--- docs/infrastructure_and_maintenance/background_tasks.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/api/event_reference/discounts_events.md b/docs/api/event_reference/discounts_events.md index 235b936134..6b5f496218 100644 --- a/docs/api/event_reference/discounts_events.md +++ b/docs/api/event_reference/discounts_events.md @@ -14,7 +14,7 @@ The events below are dispatched when managing [discounts](discounts_guide.md): | Event | Dispatched by | |---|---| -|[BeforeCreateDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeCreateDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | +|[`BeforeCreateDiscountEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeCreateDiscountEvent.html)| [`DiscountServiceInterface::createDiscount()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html#method_createDiscount) | |[CreateDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-CreateDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | |[BeforeEnableDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeEnableDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | |[EnableDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-EnableDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | diff --git a/docs/discounts/configure_discounts.md b/docs/discounts/configure_discounts.md index be9bbf54ea..067d3b4bc0 100644 --- a/docs/discounts/configure_discounts.md +++ b/docs/discounts/configure_discounts.md @@ -32,7 +32,7 @@ ibexa: ## Discount re-indexing -Discounts feature uses [[= product_name_base =]] Messenger to reindex discounts and product prices in the background. +Discounts feature uses [[= product_name_base =]] Messenger to reindex discounts and product prices as [background tasks](background_tasks.md). This way changes are processed efficiently without slowing down the system and disrupting the user experience. When triggered periodically, the `ibexa:discounts:reindex` command identifies discounts that require re-indexing, ensuring prices always remain up-to-date. @@ -43,7 +43,7 @@ To run discount re-indexing in the background: 1\. Make sure that the transport layer is [defined properly](background_tasks.md#configure-package) in [[= product_name_base =]] Messenger configuration. -2\. Make sure that the worker starts together with the application to watch the transport bus: +2\. Make sure that the [worker starts](background_tasks.md#start-worker) together with the application to watch the transport bus: ``` bash php bin/console messenger:consume ibexa.messenger.transport --bus=ibexa.messenger.bus @@ -57,7 +57,7 @@ php bin/console ibexa:discounts:reindex !!! note "Deploying Symfony Messenger" - For more information about deploying the Messenger to production, see [Symfony documentation](https://symfony.com/doc/current/messenger.html#deploying-to-production). + For more information about deploying the Messenger to production, see [Symfony documentation]([[= symfony_doc =]]/messenger.html#deploying-to-production). ## Rate limiting diff --git a/docs/infrastructure_and_maintenance/background_tasks.md b/docs/infrastructure_and_maintenance/background_tasks.md index f9037fd0dd..d669434e6f 100644 --- a/docs/infrastructure_and_maintenance/background_tasks.md +++ b/docs/infrastructure_and_maintenance/background_tasks.md @@ -8,7 +8,7 @@ month_change: true 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. Running such operations in real time could slow down the system and disrupt the user experience. -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. +To solve this, [[= product_name =]] provides a package called [[= product_name_base =]] Messenger, which is an overlay to [Symfony Messenger]([[= symfony_doc ==]]/messenger.html), and it's job is to queue tasks and run them in the background. [[= product_name =]] 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. From 5e75f6f4148718c6916220904773a60190c4aafe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20D=C4=85browski?= <64841871+dabrt@users.noreply.github.com> Date: Wed, 1 Oct 2025 16:27:25 +0200 Subject: [PATCH 12/15] Added dispatchers to discount events --- docs/api/event_reference/discounts_events.md | 46 +++++++++---------- .../background_tasks.md | 2 +- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/docs/api/event_reference/discounts_events.md b/docs/api/event_reference/discounts_events.md index 6b5f496218..65486753ea 100644 --- a/docs/api/event_reference/discounts_events.md +++ b/docs/api/event_reference/discounts_events.md @@ -10,18 +10,18 @@ month_change: true ## Discount management -The events below are dispatched when managing [discounts](discounts_guide.md): +The events below are dispatched when managing [`discounts`](discounts_guide.md): | Event | Dispatched by | |---|---| |[`BeforeCreateDiscountEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeCreateDiscountEvent.html)| [`DiscountServiceInterface::createDiscount()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html#method_createDiscount) | -|[CreateDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-CreateDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | -|[BeforeEnableDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeEnableDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | -|[EnableDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-EnableDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | -|[BeforeDeleteDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeDeleteDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | -|[DeleteDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-DeleteDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | -|[BeforeUpdateDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeUpdateDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html)| -|[UpdateDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-UpdateDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | +|[`CreateDiscountEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-CreateDiscountEvent.html)| [`DiscountServiceInterface::createDiscount()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html#method_createDiscount) | +|[`BeforeEnableDiscountEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeEnableDiscountEvent.html)| [`DiscountServiceInterface::enableDiscount()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html#method_enableDiscount) | +|[`EnableDiscountEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-EnableDiscountEvent.html)| [`DiscountServiceInterface::enableDiscount()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html#method_enableDiscount) | +|[`BeforeDeleteDiscountEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeDeleteDiscountEvent.html)| [`DiscountServiceInterface::deleteDiscount()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html#method_deleteDiscount) | +|[`DeleteDiscountEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-DeleteDiscountEvent.html)| [`DiscountServiceInterface::deleteDiscount()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html#method_deleteDiscount) | +|[`BeforeUpdateDiscountEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeUpdateDiscountEvent.html)| [`DiscountServiceInterface::updateDiscount()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html#method_updateDiscount) | +|[`UpdateDiscountEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-UpdateDiscountEvent.html)| [`DiscountServiceInterface::updateDiscount()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html#method_updateDiscount) | ## Form events @@ -31,10 +31,10 @@ The events below allow you to customize the discounts creation wizard: | Event | Dispatched by | |---|---| -|[CreateDiscountCreateStructEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-CreateDiscountCreateStructEvent.html) | [DiscountFormMapperInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountFormMapperInterface.html)| -|[CreateDiscountUpdateStructEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-CreateDiscountUpdateStructEvent.html) | [DiscountFormMapperInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountFormMapperInterface.html)| -|[CreateFormDataEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-CreateFormDataEvent.html) | [DiscountFormMapperInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountFormMapperInterface.html)| -|[MapDiscountToFormDataEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-MapDiscountToFormDataEvent.html) | [DiscountFormMapperInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountFormMapperInterface.html) | +|[`CreateDiscountCreateStructEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-CreateDiscountCreateStructEvent.html) | [`DiscountFormMapperInterface::mapCreateDataToStruct`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountFormMapperInterface.html#method_mapCreateDataToStruct)| +|[`CreateDiscountUpdateStructEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-CreateDiscountUpdateStructEvent.html) | [`DiscountFormMapperInterface::mapUpdateDataToStruct`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountFormMapperInterface.html#method_mapUpdateDataToStruct)| +|[`CreateFormDataEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-CreateFormDataEvent.html) | [`DiscountFormMapperInterface::createFormData`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountFormMapperInterface.html#method_createFormData)| +|[`MapDiscountToFormDataEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-MapDiscountToFormDataEvent.html) | [`DiscountFormMapperInterface::mapDiscountToFormData`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountFormMapperInterface.html#method_mapDiscountToFormData) | ### Form steps @@ -42,20 +42,20 @@ The following events are dispatched when rendering each step of the discount wiz | Event | Event name | |---|---| -|[CreateFormDataEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-Step-CreateFormDataEvent.html)| `ibexa.discounts.form_mapper..create_form_data`| -|[MapCreateDataToStructEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-Step-MapCreateDataToStructEvent.html)|`ibexa.discounts.form_mapper..map_create_data_to_struct`| -|[MapDiscountToFormDataEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-Step-MapDiscountToFormDataEvent.html)| `ibexa.discounts.form_mapper..map_discount_to_form_data`| -|[MapUpdateDataToStructEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-Step-MapUpdateDataToStructEvent.html)|`ibexa.discounts.form_mapper..map_update_data_to_struct `| +|[`CreateFormDataEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-Step-CreateFormDataEvent.html)| `ibexa.discounts.form_mapper..create_form_data`| +|[`MapCreateDataToStructEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-Step-MapCreateDataToStructEvent.html)|`ibexa.discounts.form_mapper..map_create_data_to_struct`| +|[`MapDiscountToFormDataEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-Step-MapDiscountToFormDataEvent.html)| `ibexa.discounts.form_mapper..map_discount_to_form_data`| +|[`MapUpdateDataToStructEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-Step-MapUpdateDataToStructEvent.html)|`ibexa.discounts.form_mapper..map_update_data_to_struct `| The event classes are shared between steps, but they are dispatched with different names. Each step form mapper dispatches its own set of events. | Form mapper | Step identifier | |---|---| -| [ConditionsMapperInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-FormMapper-ConditionsMapperInterface.html)| [`conditions`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-Form-Data-ConditionsInterface.html#constant_IDENTIFIER) | -| [GeneralPropertiesMapperInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-FormMapper-GeneralPropertiesMapperInterface.html)| [`general_properties`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-Form-Data-GeneralPropertiesInterface.html#constant_IDENTIFIER) | -| [ProductConditionsMapperInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-FormMapper-ProductConditionsMapperInterface.html)| [`products`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-Form-Data-ProductConditionInterface.html#constant_IDENTIFIER) | -| [UserConditionsMapperInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-FormMapper-UserConditionsMapperInterface.html)| [`target_group`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-Form-Data-UserConditionInterface.html#constant_IDENTIFIER) | +| [`ConditionsMapperInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-FormMapper-ConditionsMapperInterface.html)| [`conditions`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-Form-Data-ConditionsInterface.html#constant_IDENTIFIER) | +| [`GeneralPropertiesMapperInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-FormMapper-GeneralPropertiesMapperInterface.html)| [`general_properties`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-Form-Data-GeneralPropertiesInterface.html#constant_IDENTIFIER) | +| [`ProductConditionsMapperInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-FormMapper-ProductConditionsMapperInterface.html)| [`products`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-Form-Data-ProductConditionInterface.html#constant_IDENTIFIER) | +| [`UserConditionsMapperInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-FormMapper-UserConditionsMapperInterface.html)| [`target_group`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-Form-Data-UserConditionInterface.html#constant_IDENTIFIER) | ### Back office @@ -63,8 +63,8 @@ These events are dispatched by the back office controllers after user chooses th | Event | Dispatched by | Description | |---|---|---| -[PreDiscountCreateEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-Form-Event-PreDiscountCreateEvent.html) | `Ibexa\Bundle\Discounts\Controller\DiscountCreateController` | Dispatched when the discount creation is finished in the back office form | -[PreDiscountUpdateEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-Form-Event-PreDiscountUpdateEvent.html) | `Ibexa\Bundle\Discounts\Controller\DiscountEditController` | Dispatched when the discount modifications is finished in the back office form | +|[`PreDiscountCreateEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-Form-Event-PreDiscountCreateEvent.html) | `Ibexa\Bundle\Discounts\Controller\DiscountCreateController` | Dispatched when the discount creation is finished in the back office form | +|[`PreDiscountUpdateEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Admin-Form-Event-PreDiscountUpdateEvent.html) | `Ibexa\Bundle\Discounts\Controller\DiscountEditController` | Dispatched when the discount modifications is finished in the back office form | ## Discount codes @@ -72,4 +72,4 @@ The event below allows you to inject your custom logic before the discount code | Event | Dispatched by | Description | |---|---|---| -|[BeforeDiscountCodeApplyEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-DiscountsCodes-Event-BeforeDiscountCodeApplyEvent.html)|`Ibexa\Bundle\DiscountsCodes\Controller\REST\DiscountCodeController`| Dispatched before a discount code is applied in the cart | +|[`BeforeDiscountCodeApplyEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-DiscountsCodes-Event-BeforeDiscountCodeApplyEvent.html)|`Ibexa\Bundle\DiscountsCodes\Controller\REST\DiscountCodeController`| Dispatched before a discount code is applied in the cart | diff --git a/docs/infrastructure_and_maintenance/background_tasks.md b/docs/infrastructure_and_maintenance/background_tasks.md index d669434e6f..5e045fc615 100644 --- a/docs/infrastructure_and_maintenance/background_tasks.md +++ b/docs/infrastructure_and_maintenance/background_tasks.md @@ -8,7 +8,7 @@ month_change: true 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. Running such operations in real time could slow down the system and disrupt the user experience. -To solve this, [[= product_name =]] provides a package called [[= product_name_base =]] Messenger, which is an overlay to [Symfony Messenger]([[= symfony_doc ==]]/messenger.html), and it's job is to queue tasks and run them in the background. +To solve this, [[= product_name =]] provides a package called [[= product_name_base =]] Messenger, which is an overlay to [Symfony Messenger]([[= symfony_doc =]]/messenger.html), and it's job is to queue tasks and run them in the background. [[= product_name =]] 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. From c3d7c29dd8145cea8593bd58b07c4cd5f97f265b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20D=C4=85browski?= <64841871+dabrt@users.noreply.github.com> Date: Thu, 2 Oct 2025 09:21:56 +0200 Subject: [PATCH 13/15] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Marek Nocoń --- .../SomeClassThatSchedulesExecutionInTheBackground.php | 2 +- docs/api/event_reference/discounts_events.md | 8 ++++---- docs/infrastructure_and_maintenance/background_tasks.md | 2 +- .../discounts_search_reference/discounts_criteria.md | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php b/code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php index 3563654987..56d4099d54 100644 --- a/code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php +++ b/code_samples/background_tasks/src/Dispatcher/SomeClassThatSchedulesExecutionInTheBackground.php @@ -2,7 +2,7 @@ namespace App\Dispatcher; -use Ibexa\Messenger\Stamp\DeduplicateStamp; +use Ibexa\Bundle\Messenger\Stamp\DeduplicateStamp; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\MessageBusInterface; diff --git a/docs/api/event_reference/discounts_events.md b/docs/api/event_reference/discounts_events.md index 65486753ea..95501f128d 100644 --- a/docs/api/event_reference/discounts_events.md +++ b/docs/api/event_reference/discounts_events.md @@ -31,10 +31,10 @@ The events below allow you to customize the discounts creation wizard: | Event | Dispatched by | |---|---| -|[`CreateDiscountCreateStructEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-CreateDiscountCreateStructEvent.html) | [`DiscountFormMapperInterface::mapCreateDataToStruct`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountFormMapperInterface.html#method_mapCreateDataToStruct)| -|[`CreateDiscountUpdateStructEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-CreateDiscountUpdateStructEvent.html) | [`DiscountFormMapperInterface::mapUpdateDataToStruct`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountFormMapperInterface.html#method_mapUpdateDataToStruct)| -|[`CreateFormDataEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-CreateFormDataEvent.html) | [`DiscountFormMapperInterface::createFormData`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountFormMapperInterface.html#method_createFormData)| -|[`MapDiscountToFormDataEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-MapDiscountToFormDataEvent.html) | [`DiscountFormMapperInterface::mapDiscountToFormData`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountFormMapperInterface.html#method_mapDiscountToFormData) | +|[`CreateDiscountCreateStructEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-CreateDiscountCreateStructEvent.html) | [`DiscountFormMapperInterface::mapCreateDataToStruct()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountFormMapperInterface.html#method_mapCreateDataToStruct)| +|[`CreateDiscountUpdateStructEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-CreateDiscountUpdateStructEvent.html) | [`DiscountFormMapperInterface::mapUpdateDataToStruct()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountFormMapperInterface.html#method_mapUpdateDataToStruct)| +|[`CreateFormDataEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-CreateFormDataEvent.html) | [`DiscountFormMapperInterface::createFormData()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountFormMapperInterface.html#method_createFormData)| +|[`MapDiscountToFormDataEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-MapDiscountToFormDataEvent.html) | [`DiscountFormMapperInterface::mapDiscountToFormData()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountFormMapperInterface.html#method_mapDiscountToFormData) | ### Form steps diff --git a/docs/infrastructure_and_maintenance/background_tasks.md b/docs/infrastructure_and_maintenance/background_tasks.md index 5e045fc615..70de189940 100644 --- a/docs/infrastructure_and_maintenance/background_tasks.md +++ b/docs/infrastructure_and_maintenance/background_tasks.md @@ -95,7 +95,7 @@ Add a service definition to `config/services.yaml`: ``` yaml services: - Ibexa\Bundle\Foo\Message\SomeHandler: + App\MessageHandler\SomeHandler: tags: - name: messenger.message_handler bus: ibexa.messenger.bus diff --git a/docs/search/discounts_search_reference/discounts_criteria.md b/docs/search/discounts_search_reference/discounts_criteria.md index ac4102e9da..56ad1da499 100644 --- a/docs/search/discounts_search_reference/discounts_criteria.md +++ b/docs/search/discounts_search_reference/discounts_criteria.md @@ -22,7 +22,7 @@ Search Criteria are found in the `Ibexa\Contracts\Discounts\Value\Query\Criterio | [PriorityCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-PriorityCriterion.html) | Find discounts by their priority | | [StartDateCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-StartDateCriterion.html) | Find discounts with given start date | | [TypeCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-TypeCriterion.html) | Find cart or catalog discounts by using constants from the [DiscountType](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-DiscountType.html) class | -| [UpdatedAtCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-UpdatedAtCriterion.html) | Find discounts based on the date and time when they were indexed | +| [UpdatedAtCriterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-Criterion-UpdatedAtCriterion.html) | Find discounts based on the date and time when they were updated | You can use the [FieldValueCriterion's constants](/api/php_api/php_api_reference/classes/Ibexa-Contracts-CoreSearch-Values-Query-Criterion-FieldValueCriterion.html#constants) like `FieldValueCriterion::COMPARISON_CONTAINS` or `FieldValueCriterion::COMPARISON_STARTS_WITH` to specify the operator for the condition. From 9db3eb1dc1ca0e3f641d0e222e623e520690e131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20D=C4=85browski?= <64841871+dabrt@users.noreply.github.com> Date: Thu, 2 Oct 2025 16:19:25 +0200 Subject: [PATCH 14/15] Add links to configuration --- docs/infrastructure_and_maintenance/background_tasks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/infrastructure_and_maintenance/background_tasks.md b/docs/infrastructure_and_maintenance/background_tasks.md index 5e045fc615..d419f5bfc5 100644 --- a/docs/infrastructure_and_maintenance/background_tasks.md +++ b/docs/infrastructure_and_maintenance/background_tasks.md @@ -65,7 +65,7 @@ Use a process manager of your choice to run the following command, or make it st php bin/console messenger:consume ibexa.messenger.transport --bus=ibexa.messenger.bus --siteaccess=` ``` -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. +In [multi-repository setups](repository_configuration.md), the worker process always works for a [SiteAccess](multisite_configuration.md#siteaccess-configuration) that you indicate by using the `--siteaccess` option, therefore you may need to run multiple workers, one for each SiteAccess. !!! warning "Multi-repository setups" From ced8ff0e4d677948dfc3ac923612da0d5b3fdf14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20D=C4=85browski?= <64841871+dabrt@users.noreply.github.com> Date: Thu, 2 Oct 2025 16:33:11 +0200 Subject: [PATCH 15/15] Mention discount re-indexing in post instaall steps --- docs/getting_started/install_ibexa_dxp.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/getting_started/install_ibexa_dxp.md b/docs/getting_started/install_ibexa_dxp.md index 411284c41e..54529d20bc 100644 --- a/docs/getting_started/install_ibexa_dxp.md +++ b/docs/getting_started/install_ibexa_dxp.md @@ -407,6 +407,10 @@ Finally, remove the temporary file: To make use of the [Link Manager](url_management.md#enabling-automatic-url-validation). +### Enable discount re-indexing [[% include 'snippets/commerce_badge.md' %]] + +Enable [discount re-indexing in the background](configure_discounts.md#discount-re-indexing). + ## [[= product_name_cloud =]] If you want to host your application on [[= product_name_cloud =]], follow the [Ibexa Cloud](install_on_ibexa_cloud.md) procedure.