Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ utilizing The RabbitMQ's [dead letter exchange](https://www.rabbitmq.com/dlx.htm
- [Features](#features)
- [How it works](#how-it-works)
- [Configuration](#configuration)
- [Skipping the retry](#skipping-the-retry)
- [License](#licence)

---

## Prerequisites

- Magento 2.4.5 or higher
Expand Down Expand Up @@ -43,6 +46,8 @@ To enable the module:
bin/magento module:enable RunAsRoot_MessageQueueRetry
```

---

## Features

- Toggle activation
Expand All @@ -52,6 +57,7 @@ bin/magento module:enable RunAsRoot_MessageQueueRetry
- Delete the message
- Download the message body

---
## How it works

The default Magento's consumer behavior is to reject the message when an exception is thrown during the consumer's execution.
Expand Down Expand Up @@ -91,6 +97,8 @@ Is possible to configure the ACL for each action in the grid and the module conf

![img.png](docs/acl.png)

---

### Configuration

Two steps are necessary to configure the retry for a queue:
Expand Down Expand Up @@ -195,11 +203,21 @@ System > Configuration > RUN-AS-ROOT > Message Queue Retry

![img.png](docs/module-configuration.png)

---

### Skipping the retry

In case you have a queue configured for retry but there is some scenario that doesn't need the message to be processed again, just add concatenate the `MESSAGE_QUEUE_SKIP_RETRY` string in the exception message. With it the message will not enter in the retry loop.

---

**Important note:** Make sure to configure the retry limit of your queue with the `queue_retry.xml` file and enable the message queue retry configuration.
If you configure the dead letter exchange and do not do the steps mentioned, the message will be in a retry loop. In other words, it will execute until the consumer processes the message without throwing an exception.
This is the default behavior for the RabbitMQ dead letter exchange and will work this way even if this module is not installed.

For more information of how to configure message queues in Magento 2, you can take a look [here](https://developer.adobe.com/commerce/php/development/components/message-queues/configuration/).

---

## License
[MIT](https://opensource.org/licenses/MIT)
5 changes: 5 additions & 0 deletions src/Plugin/HandleQueueMessageRejectPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ public function aroundReject(
return;
}

if (str_contains($rejectionMessage, 'MESSAGE_QUEUE_SKIP_RETRY')) {
$proceed($envelope, $requeue, $rejectionMessage);
return;
}

$shouldBeSavedForRetry = $this->isMessageShouldBeSavedForRetryService->execute($envelope);

if (!$shouldBeSavedForRetry) {
Expand Down
29 changes: 29 additions & 0 deletions src/Test/Unit/Plugin/HandleQueueMessageRejectPluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,33 @@ public function testItProceedIfThereIsNoError(): void

self::assertTrue($this->isProceedCalled);
}

/**
* @dataProvider skipRetryDataProvider
*/
public function testItShouldSkipRetryWhenExceptionMessageContainsAnUniqueIdentifier(string $exceptionMessage): void
{
$this->saveFailedMessageServiceMock->expects($this->never())->method('execute');
$this->isMessageShouldBeSavedForRetryServiceMock->expects($this->never())->method('execute');

$this->sut->aroundReject(
$this->queueMock,
$this->testProceedFn,
new Envelope('body'),
false,
$exceptionMessage
);

self::assertTrue($this->isProceedCalled);
}

public function skipRetryDataProvider(): array
{
return [
['Some Error MESSAGE_QUEUE_SKIP_RETRY'],
['MESSAGE_QUEUE_SKIP_RETRY'],
['Some Error MESSAGE_QUEUE_SKIP_RETRY Some Error'],
['Some Error MESSAGE_QUEUE_SKIP_RETRY Some Error MESSAGE_QUEUE_SKIP_RETRY'],
];
}
}