Skip to content

Commit 8d78491

Browse files
dabrtadriendupuismnocon
committed
IBX-10675: Document Ibexa Messenger and discount re-indexing in the background (#2909)
* API changes documented * Add messenger description * Modify configure_discounts.md * Add dispatchers to discount events * Mention discount re-indexing in post install steps --------- Co-authored-by: dabrt <[email protected]> Co-authored-by: Adrien Dupuis <[email protected]> Co-authored-by: Marek Nocoń <[email protected]>
1 parent 9e26e57 commit 8d78491

File tree

12 files changed

+232
-27
lines changed

12 files changed

+232
-27
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace App\Dispatcher;
4+
5+
use Ibexa\Bundle\Messenger\Stamp\DeduplicateStamp;
6+
use Symfony\Component\Messenger\Envelope;
7+
use Symfony\Component\Messenger\MessageBusInterface;
8+
9+
final class SomeClassThatSchedulesExecutionInTheBackground
10+
{
11+
private MessageBusInterface $bus;
12+
13+
public function __construct(MessageBusInterface $bus)
14+
{
15+
$this->bus = $bus;
16+
}
17+
18+
public function schedule(object $message): void
19+
{
20+
// Dispatch directly. Message is wrapped with envelope without any stamps.
21+
$this->bus->dispatch($message);
22+
23+
// Alternatively, wrap with stamps. In this case, DeduplicateStamp ensures
24+
// that if similar command exists in the queue (or is being processed)
25+
// it will not be queued again.
26+
$envelope = Envelope::wrap(
27+
$message,
28+
[new DeduplicateStamp('command-name-1')]
29+
);
30+
31+
$this->bus->dispatch($envelope);
32+
}
33+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace App\Message;
4+
5+
class SomeMessage
6+
{
7+
// Add properties and methods as needed for your message.
8+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace App\MessageHandler;
4+
5+
use App\Message\SomeMessage;
6+
7+
final class SomeHandler
8+
{
9+
public function __invoke(SomeMessage $message): void
10+
{
11+
// Handle message.
12+
}
13+
}

docs/api/event_reference/discounts_events.md

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,18 @@ month_change: true
1111

1212
## Discount management
1313

14-
The events below are dispatched when managing [discounts](discounts_guide.md):
14+
The events below are dispatched when managing [`discounts`](discounts_guide.md):
1515

1616
| Event | Dispatched by |
1717
|---|---|
18-
|[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) |
19-
|[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) |
20-
|[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) |
21-
|[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) |
22-
|[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)|
23-
|[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) |
18+
|[`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) |
19+
|[`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) |
20+
|[`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) |
21+
|[`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) |
22+
|[`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) |
23+
|[`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) |
24+
|[`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) |
25+
|[`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) |
2426

2527
## Form events
2628

@@ -30,45 +32,45 @@ The events below allow you to customize the discounts creation wizard:
3032

3133
| Event | Dispatched by |
3234
|---|---|
33-
|[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)|
34-
|[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)|
35-
|[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)|
36-
|[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) |
35+
|[`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)|
36+
|[`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)|
37+
|[`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)|
38+
|[`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) |
3739

3840
### Form steps
3941

4042
The following events are dispatched when rendering each step of the discount wizard, allowing you to add new fields to it:
4143

4244
| Event | Event name |
4345
|---|---|
44-
|[CreateFormDataEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-Step-CreateFormDataEvent.html)| `ibexa.discounts.form_mapper.<step_identifier>.create_form_data`|
45-
|[MapCreateDataToStructEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-Step-MapCreateDataToStructEvent.html)|`ibexa.discounts.form_mapper.<step_identifier>.map_create_data_to_struct`|
46-
|[MapDiscountToFormDataEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-Step-MapDiscountToFormDataEvent.html)| `ibexa.discounts.form_mapper.<step_identifier>.map_discount_to_form_data`|
47-
|[MapUpdateDataToStructEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-Step-MapUpdateDataToStructEvent.html)|`ibexa.discounts.form_mapper.<step_identifier>.map_update_data_to_struct `|
46+
|[`CreateFormDataEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-Step-CreateFormDataEvent.html)| `ibexa.discounts.form_mapper.<step_identifier>.create_form_data`|
47+
|[`MapCreateDataToStructEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-Step-MapCreateDataToStructEvent.html)|`ibexa.discounts.form_mapper.<step_identifier>.map_create_data_to_struct`|
48+
|[`MapDiscountToFormDataEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-Step-MapDiscountToFormDataEvent.html)| `ibexa.discounts.form_mapper.<step_identifier>.map_discount_to_form_data`|
49+
|[`MapUpdateDataToStructEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-Step-MapUpdateDataToStructEvent.html)|`ibexa.discounts.form_mapper.<step_identifier>.map_update_data_to_struct `|
4850

4951
The event classes are shared between steps, but they are dispatched with different names.
5052
Each step form mapper dispatches its own set of events.
5153

5254
| Form mapper | Step identifier |
5355
|---|---|
54-
| [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) |
55-
| [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) |
56-
| [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) |
57-
| [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) |
56+
| [`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) |
57+
| [`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) |
58+
| [`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) |
59+
| [`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) |
5860

5961
### Back office
6062

6163
These events are dispatched by the back office controllers after user chooses the "Save" action when creating or updating a discount.
6264

6365
| Event | Dispatched by | Description |
6466
|---|---|---|
65-
[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 |
66-
[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 |
67+
|[`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 |
68+
|[`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 |
6769

6870
## Discount codes
6971

7072
The event below allows you to inject your custom logic before the discount code is applied to a product in cart:
7173

7274
| Event | Dispatched by | Description |
7375
|---|---|---|
74-
|[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 |
76+
|[`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 |

docs/discounts/configure_discounts.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,35 @@ ibexa:
3131
products_list_per_page_limit: 15
3232
```
3333
34+
## Discount re-indexing
35+
36+
Discounts feature uses [[= product_name_base =]] Messenger to reindex discounts and product prices as [background tasks](background_tasks.md).
37+
This way changes are processed efficiently without slowing down the system and disrupting the user experience.
38+
39+
When triggered periodically, the `ibexa:discounts:reindex` command identifies discounts that require re-indexing, ensuring prices always remain up-to-date.
40+
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.
41+
The worker passes the messages to the handler, which then starts the re-indexing process at the most convenient moment.
42+
43+
To run discount re-indexing in the background:
44+
45+
1\. Make sure that the transport layer is [defined properly](background_tasks.md#configure-package) in [[= product_name_base =]] Messenger configuration.
46+
47+
2\. Make sure that the [worker starts](background_tasks.md#start-worker) together with the application to watch the transport bus:
48+
49+
``` bash
50+
php bin/console messenger:consume ibexa.messenger.transport --bus=ibexa.messenger.bus
51+
```
52+
53+
3\. Use a scheduler of your choice, for example, [cron](https://en.wikipedia.org/wiki/Cron), to periodically run the following command:
54+
55+
``` bash
56+
php bin/console ibexa:discounts:reindex
57+
```
58+
59+
!!! note "Deploying Symfony Messenger"
60+
61+
For more information about deploying the Messenger to production, see [Symfony documentation]([[= symfony_doc =]]/messenger.html#deploying-to-production).
62+
3463
## Rate limiting
3564

3665
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).

docs/discounts/discounts_guide.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,15 @@ You can also limit the usage per customer:
115115
- limited use: every customer can use the code a specified number of times
116116
- unlimited
117117

118+
### Discount re-indexing
119+
120+
Discounts affect the prices shown in the product catalog.
121+
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.
122+
123+
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.
124+
125+
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.
126+
118127
## Capabilities
119128

120129
### Management

docs/getting_started/install_ibexa_dxp.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,10 @@ Finally, remove the temporary file:
421421

422422
To make use of the [Link Manager](url_management.md#enabling-automatic-url-validation).
423423

424+
### Enable discount re-indexing [[% include 'snippets/commerce_badge.md' %]]
425+
426+
Enable [discount re-indexing in the background](configure_discounts.md#discount-re-indexing).
427+
424428
## [[= product_name_cloud =]]
425429

426430
If you want to host your application on [[= product_name_cloud =]], follow the [Ibexa Cloud](install_on_ibexa_cloud.md) procedure.

0 commit comments

Comments
 (0)