Skip to content

Commit 77c2847

Browse files
committed
Allow setting retry delay by RecoverableExceptionInterface
1 parent 6d6dd4a commit 77c2847

File tree

5 files changed

+50
-1
lines changed

5 files changed

+50
-1
lines changed

src/Symfony/Component/Messenger/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ CHANGELOG
77
* `WrappedExceptionsInterface` now extends PHP's `Throwable` interface
88
* Add `#[AsMessage]` attribute with `$transport` parameter for message routing
99
* Add `--format` option to the `messenger:stats` command
10+
* Add `getRetryDelay` method to `RecoverableExceptionInterface`
1011

1112
7.1
1213
---

src/Symfony/Component/Messenger/EventListener/SendFailedMessageForRetryListener.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,12 @@ public function onMessageFailed(WorkerMessageFailedEvent $event): void
6363

6464
++$retryCount;
6565

66-
$delay = $retryStrategy->getWaitingTime($envelope, $throwable);
66+
$delay = null;
67+
if ($throwable instanceof RecoverableExceptionInterface && method_exists($throwable, 'getRetryDelay')) {
68+
$delay = $throwable->getRetryDelay();
69+
}
70+
71+
$delay ??= $retryStrategy->getWaitingTime($envelope, $throwable);
6772

6873
$this->logger?->warning('Error thrown while handling message {class}. Sending for retry #{retryCount} using {delay} ms delay. Error: "{error}"', $context + ['retryCount' => $retryCount, 'delay' => $delay, 'error' => $throwable->getMessage(), 'exception' => $throwable]);
6974

src/Symfony/Component/Messenger/Exception/RecoverableExceptionInterface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
* and the message should be retried, a handler can throw such an exception.
1919
*
2020
* @author Jérémy Derussé <jeremy@derusse.com>
21+
*
22+
* @method int|null getRetryDelay()
2123
*/
2224
interface RecoverableExceptionInterface extends \Throwable
2325
{

src/Symfony/Component/Messenger/Exception/RecoverableMessageHandlingException.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,13 @@
1818
*/
1919
class RecoverableMessageHandlingException extends RuntimeException implements RecoverableExceptionInterface
2020
{
21+
public function __construct(string $message = "", int $code = 0, ?\Throwable $previous = null, private readonly ?int $retryDelay = null)
22+
{
23+
parent::__construct($message, $code, $previous);
24+
}
25+
26+
public function getRetryDelay(): ?int
27+
{
28+
return $this->retryDelay;
29+
}
2130
}

src/Symfony/Component/Messenger/Tests/EventListener/SendFailedMessageForRetryListenerTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,38 @@ public function testRecoverableStrategyCausesRetry()
7676
$listener->onMessageFailed($event);
7777
}
7878

79+
public function testRecoverableExceptionRetryDelayOverridesStrategy()
80+
{
81+
$sender = $this->createMock(SenderInterface::class);
82+
$sender->expects($this->once())->method('send')->willReturnCallback(function (Envelope $envelope) {
83+
$delayStamp = $envelope->last(DelayStamp::class);
84+
$redeliveryStamp = $envelope->last(RedeliveryStamp::class);
85+
86+
$this->assertInstanceOf(DelayStamp::class, $delayStamp);
87+
$this->assertSame(1234, $delayStamp->getDelay());
88+
89+
$this->assertInstanceOf(RedeliveryStamp::class, $redeliveryStamp);
90+
$this->assertSame(1, $redeliveryStamp->getRetryCount());
91+
92+
return $envelope;
93+
});
94+
$senderLocator = new Container();
95+
$senderLocator->set('my_receiver', $sender);
96+
$retryStrategy = $this->createMock(RetryStrategyInterface::class);
97+
$retryStrategy->expects($this->never())->method('isRetryable');
98+
$retryStrategy->expects($this->never())->method('getWaitingTime');
99+
$retryStrategyLocator = new Container();
100+
$retryStrategyLocator->set('my_receiver', $retryStrategy);
101+
102+
$listener = new SendFailedMessageForRetryListener($senderLocator, $retryStrategyLocator);
103+
104+
$exception = new RecoverableMessageHandlingException('retry', retryDelay: 1234);
105+
$envelope = new Envelope(new \stdClass());
106+
$event = new WorkerMessageFailedEvent($envelope, 'my_receiver', $exception);
107+
108+
$listener->onMessageFailed($event);
109+
}
110+
79111
public function testEnvelopeIsSentToTransportOnRetry()
80112
{
81113
$exception = new \Exception('no!');

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy