Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NEXT-31249 - async low priority queue documentation #1153

Merged
merged 5 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions guides/hosting/infrastructure/message-queue.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ nav:

## Overview

::: warning
This guide contains the `async_low_priority` queue which is only available in version 6.5.7.0 and above. You must not configure this queue in older versions as the messenger:consume command will fail.
MoritzKrafeld marked this conversation as resolved.
Show resolved Hide resolved
:::

Shopware uses the Symfony Messenger component and Enqueue to handle asynchronous messages. This allows tasks to be processed in the background. Thus, tasks can be processed independently of timeouts or system crashes. By default, tasks in Shopware are stored in the database and processed via the browser as long as you are logged into the Administration. This is a simple and fast method for the development process, but not recommended for production systems. With multiple users logged into the Administration, this can lead to a high CPU load and interfere with the smooth execution of PHP FPM.

## Message queue on production systems
Expand Down Expand Up @@ -41,6 +45,14 @@ You can configure the command just to run a certain amount of time and to stop i
bin/console messenger:consume async --time-limit=60 --memory-limit=128M
```

You can also configure the command to consume messages from multiple transports, in order to prioritize them to your needs, as it is recommended by the [Symfony documentation](https://symfony.com/doc/current/messenger.html#prioritized-transports):
MoritzKrafeld marked this conversation as resolved.
Show resolved Hide resolved

```bash

```bash
bin/console messenger:consume async async_low_priority
fschmtt marked this conversation as resolved.
Show resolved Hide resolved
MoritzKrafeld marked this conversation as resolved.
Show resolved Hide resolved
```

For more information about the command and its configuration, use the -h option:

```bash
Expand Down Expand Up @@ -77,7 +89,7 @@ User=www-data # Change this to webserver's user name
Restart=always
# Change the path to your shop path
WorkingDirectory=/var/www/html
ExecStart=php /var/www/html/bin/console messenger:consume --time-limit=60 --memory-limit=512M async
ExecStart=php /var/www/html/bin/console messenger:consume --time-limit=60 --memory-limit=512M async async_low_priority
MoritzKrafeld marked this conversation as resolved.
Show resolved Hide resolved
fschmtt marked this conversation as resolved.
Show resolved Hide resolved

[Install]
WantedBy=shopware_consumer.target
Expand Down Expand Up @@ -108,6 +120,10 @@ Please refer to the [Symfony documentation](https://symfony.com/doc/current/mess

### Admin worker

::: warning
The `transports` option can only be configured with the `async_low_priority` transport if you are on version 6.5.7.0 or above. You must not the `async_low_priority` in lower versions as the admin worker will fail.
:::

The admin worker, if used, can be configured in the general `shopware.yml` configuration. If you want to use the admin worker, you have to specify each transport that was previously configured. The poll interval is the time in seconds that the admin worker polls messages from the queue. After the poll interval is over, the request terminates, and the Administration initiates a new request.

```yaml
Expand All @@ -116,7 +132,7 @@ shopware:
admin_worker:
enable_admin_worker: true
poll_interval: 30
transports: ["async"]
transports: ["async", "async_low_priority"]
keulinho marked this conversation as resolved.
Show resolved Hide resolved
```

## Sending mails over the message queue
Expand All @@ -143,6 +159,7 @@ You can find all available transport options in the Symfony Messenger documentat
Following environment variables are in use out of the box:

* `MESSENGER_TRANSPORT_DSN` - The DSN to the transport to use (e.g. `doctrine://default`).
* `MESSENGER_TRANSPORT_LOW_PRIORITY_DSN` - The DSN to the transport to use for low priority messages (e.g. `doctrine://default?queue_name=async_low_priority`).
* `MESSENGER_TRANSPORT_FAILURE_DSN` - The DSN to the transport to use for failed messages (e.g. `doctrine://default?queue_name=failed`).

## Worker count for efficient message processing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ nav:

## Overview

::: warning
This guide contains the `async_low_priority` queue which is only available in version 6.5.7.0 and above. You must not configure this queue in older versions as the messenger:consume command will fail.
:::

In this guide you'll learn how to create a message handler.

A [handler](https://symfony.com/doc/current/messenger.html#creating-a-message-handler) gets called once the message is dispatched by the `handle_messages` middleware. Handlers do the actual processing of the message.
Expand Down Expand Up @@ -49,7 +53,14 @@ There is a console command to start a worker that will receive incoming messages
bin/console messenger:consume async
```

Where `async` is the transport you want to consume message from. There is also an API-Route that lets you consume messages for a given transport. Just post to the route `/api/_action/message-queue/consume` and define the transport from which you want to consume:
You can also append more transports to the command, so the worker will consume messages from multiple transports which will result in prioritisation as mentioned in [Prioritized Transports](https://symfony.com/doc/current/messenger.html#prioritized-transports):
MoritzKrafeld marked this conversation as resolved.
Show resolved Hide resolved

```bash
//
bin/console messenger:consume async async_low_priority
fschmtt marked this conversation as resolved.
Show resolved Hide resolved
```

Where `async` and `async_low_priority` are the transports you want to consume messages from. There is also an API-Route that lets you consume messages for a given transport. Just post to the route `/api/_action/message-queue/consume` and define the transport from which you want to consume:
fschmtt marked this conversation as resolved.
Show resolved Hide resolved
MoritzKrafeld marked this conversation as resolved.
Show resolved Hide resolved

```js
// on
Expand Down Expand Up @@ -77,12 +88,12 @@ The recommended way to consume messages is through the cli command. You can conf

```bash
//
bin/console messenger:consume async --time-limit=60
bin/console messenger:consume async async_low_priority --time-limit=60
fschmtt marked this conversation as resolved.
Show resolved Hide resolved
MoritzKrafeld marked this conversation as resolved.
Show resolved Hide resolved
```

```bash
//
bin/console messenger:consume async --memory-limit=128M
bin/console messenger:consume async async_low_priority --memory-limit=128M
fschmtt marked this conversation as resolved.
Show resolved Hide resolved
```

For more information about the command and its configuration use the `-h` option:
Expand Down Expand Up @@ -164,6 +175,10 @@ You can route messages by their classname and use the asterisk as a fallback for

### Admin worker

::: warning
The `transports` option can only be configured with the `async_low_priority` transport if you are on version 6.5.7.0 or above. You must not the `async_low_priority` in lower versions as the admin worker will fail.
MoritzKrafeld marked this conversation as resolved.
Show resolved Hide resolved
:::

The admin-worker can be configured or disabled in the general `shopware.yml` configuration. If you want to use the admin worker you have to specify each transport, that previously was configured. The poll interval is the time in seconds that the admin-worker polls messages from the queue. After the poll-interval is over the request terminates and the Administration initiates a new request.

```yaml
Expand All @@ -172,7 +187,7 @@ shopware:
admin_worker:
enable_admin_worker: true
poll_interval: 30
transports: ["async"]
transports: ["async", "async_low_priority"]
keulinho marked this conversation as resolved.
Show resolved Hide resolved
```

## Next steps
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ As most guides, this guide is also built upon the [Plugin base guide](../../plug

## Create a message

First, we have to create a new message class in the directory `<plugin root>/MessageQueue/Message`. In this example, we create a `SmsNotification` that contains a string with content. By default, all messages are handled synchronously, to change the behavior to asynchronously we have to implement the `AsyncMessageInterface` interface.
First, we have to create a new message class in the directory `<plugin root>/MessageQueue/Message`. In this example, we create a `SmsNotification` that contains a string with content. By default, all messages are handled synchronously, to change the behavior to asynchronously we have to implement the `AsyncMessageInterface` interface. For more information about asynchronous messages, have a look at our guide about [Handling asynchronous messages](handle-asynchronous-messages.md).

Here's an example:

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
nav:
title: Handle asynchronous messages
position: 40

---

# Handle asynchronous messages

## Overview

::: warning
This guide contains the `async_low_priority` queue which is only available in version 6.5.7.0 and above. You must not configure this queue in older versions as the messenger:consume command will fail.
MoritzKrafeld marked this conversation as resolved.
Show resolved Hide resolved
:::

In this guide you will learn how to handle asynchronous messages and the difference between the asynchronous queues.

## Prerequisites

This guide is built upon the [Add message to queue guide](add-message-to-queue), so you should have read that first.

## Different queues
MoritzKrafeld marked this conversation as resolved.
Show resolved Hide resolved

Currently, there are two different queues for asynchronous messages which allow us to have different prioritized queues as mentioned in [Prioritized Transports](https://symfony.com/doc/current/messenger.html#prioritized-transports). The first one is the `async` queue which can be used if a message implements the `AsyncMessageInterface` as mentioned in [Create a message](add-message-to-queue#create-a-message).

The second queue is the `async_low_priority` queue which will also handle the messages asynchronously, but with a lower priority, as this queue should be handled once the `async` queue is empty. This queue can be used if a message implements the `AsyncLowPriorityMessageInterface`.

Here's an example:

```php
// <plugin root>/src/MessageQueue/Message/EmailNotification.php
<?php declare(strict_types=1);

namespace Swag\BasicExample\MessageQueue\Message;

use Shopware\Core\Framework\MessageQueue\AsyncLowPriorityMessageInterface;

class EmailNotification implements AsyncLowPriorityMessageInterface
{
private string $content;

public function __construct(string $content)
{
$this->content = $content;
}

public function getContent(): string
{
return $this->content;
}
}
```

## Retry strategies

Both queues have the same retry strategy. If a message fails to be handled, it will be retried up to 3 times with a starting delay of 1 second, doubling after each retry. After the third retry, the message will be moved to the `failed` queue.

## More interesting topics

* [Message Queue](add-message-to-queue)
* [Message Handler](add-message-handler)