Skip to content

Commit 75b57e3

Browse files
dabrtadriendupuismnocon
authored
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 e6a3416 commit 75b57e3

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
@@ -10,16 +10,18 @@ month_change: true
1010

1111
## Discount management
1212

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

1515
| Event | Dispatched by |
1616
|---|---|
17-
|[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) |
18-
|[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) |
19-
|[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) |
20-
|[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) |
21-
|[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)|
22-
|[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) |
17+
|[`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) |
18+
|[`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) |
19+
|[`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) |
20+
|[`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) |
21+
|[`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) |
22+
|[`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) |
23+
|[`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) |
24+
|[`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) |
2325

2426
## Form events
2527

@@ -29,45 +31,45 @@ The events below allow you to customize the discounts creation wizard:
2931

3032
| Event | Dispatched by |
3133
|---|---|
32-
|[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)|
33-
|[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)|
34-
|[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)|
35-
|[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) |
34+
|[`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)|
35+
|[`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)|
36+
|[`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)|
37+
|[`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) |
3638

3739
### Form steps
3840

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

4143
| Event | Event name |
4244
|---|---|
43-
|[CreateFormDataEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-Step-CreateFormDataEvent.html)| `ibexa.discounts.form_mapper.<step_identifier>.create_form_data`|
44-
|[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`|
45-
|[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`|
46-
|[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 `|
45+
|[`CreateFormDataEvent`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-Step-CreateFormDataEvent.html)| `ibexa.discounts.form_mapper.<step_identifier>.create_form_data`|
46+
|[`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`|
47+
|[`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`|
48+
|[`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 `|
4749

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

5153
| Form mapper | Step identifier |
5254
|---|---|
53-
| [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) |
54-
| [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) |
55-
| [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) |
56-
| [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) |
55+
| [`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) |
56+
| [`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) |
57+
| [`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) |
58+
| [`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) |
5759

5860
### Back office
5961

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

6264
| Event | Dispatched by | Description |
6365
|---|---|---|
64-
[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 |
65-
[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 |
66+
|[`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 |
67+
|[`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 |
6668

6769
## Discount codes
6870

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

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

3564
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
@@ -113,6 +113,15 @@ You can also limit the usage per customer:
113113
- limited use: every customer can use the code a specified number of times
114114
- unlimited
115115

116+
### Discount re-indexing
117+
118+
Discounts affect the prices shown in the product catalog.
119+
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.
120+
121+
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.
122+
123+
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.
124+
116125
## Capabilities
117126

118127
### Management

docs/getting_started/install_ibexa_dxp.md

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

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

410+
### Enable discount re-indexing [[% include 'snippets/commerce_badge.md' %]]
411+
412+
Enable [discount re-indexing in the background](configure_discounts.md#discount-re-indexing).
413+
410414
## [[= product_name_cloud =]]
411415

412416
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)