Skip to content

Commit 01a34d7

Browse files
committed
Use AsyncDecoratorTrait and add a RetryStrategy
1 parent 92d2a66 commit 01a34d7

File tree

6 files changed

+286
-313
lines changed

6 files changed

+286
-313
lines changed

src/Symfony/Component/HttpClient/Response/RetryResponse.php

-224
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpClient\Retry;
13+
14+
use Symfony\Component\Messenger\Exception\InvalidArgumentException;
15+
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
16+
use Symfony\Contracts\HttpClient\ResponseInterface;
17+
18+
/**
19+
* A retry strategy with a constant or exponential retry delay.
20+
*
21+
* For example, if $delayMilliseconds=10000 & $multiplier=1 (default),
22+
* each retry will wait exactly 10 seconds.
23+
*
24+
* But if $delayMilliseconds=10000 & $multiplier=2:
25+
* * Retry 1: 10 second delay
26+
* * Retry 2: 20 second delay (10000 * 2 = 20000)
27+
* * Retry 3: 40 second delay (20000 * 2 = 40000)
28+
*
29+
* @author Ryan Weaver <ryan@symfonycasts.com>
30+
* @author Jérémy Derussé <jeremy@derusse.com>
31+
*
32+
* @final
33+
*/
34+
class MultiplierRetryStrategy implements RetryStrategyInterface
35+
{
36+
private $statusCodes;
37+
private $maxRetries;
38+
private $delayMilliseconds;
39+
private $multiplier;
40+
private $maxDelayMilliseconds;
41+
42+
/**
43+
* @param array $statusCodes List of HTTP status codes that trigger a retry
44+
* @param int $maxRetries The maximum number of times to retry
45+
* @param int $delayMilliseconds Amount of time to delay (or the initial value when multiplier is used)
46+
* @param float $multiplier Multiplier to apply to the delay each time a retry occurs
47+
* @param int $maxDelayMilliseconds Maximum delay to allow (0 means no maximum)
48+
*/
49+
public function __construct(array $statusCodes = [423, 425, 429, 500, 502, 503, 504, 507, 510], int $maxRetries = 3, int $delayMilliseconds = 1000, float $multiplier = 1, int $maxDelayMilliseconds = 0)
50+
{
51+
$this->statusCodes = $statusCodes;
52+
$this->maxRetries = $maxRetries;
53+
54+
if ($delayMilliseconds < 0) {
55+
throw new InvalidArgumentException(sprintf('Delay must be greater than or equal to zero: "%s" passed.', $delayMilliseconds));
56+
}
57+
$this->delayMilliseconds = $delayMilliseconds;
58+
59+
if ($multiplier < 1) {
60+
throw new InvalidArgumentException(sprintf('Multiplier must be greater than zero: "%s" passed.', $multiplier));
61+
}
62+
$this->multiplier = $multiplier;
63+
64+
if ($maxDelayMilliseconds < 0) {
65+
throw new InvalidArgumentException(sprintf('Max delay must be greater than or equal to zero: "%s" passed.', $maxDelayMilliseconds));
66+
}
67+
$this->maxDelayMilliseconds = $maxDelayMilliseconds;
68+
}
69+
70+
public function shouldRetry(ResponseInterface $response, \Throwable $throwable = null): bool
71+
{
72+
}
73+
74+
public function isRetryable(int $retryCount, ResponseInterface $response, \Throwable $throwable = null): bool
75+
{
76+
if ($retryCount >= $this->maxRetries) {
77+
return false;
78+
}
79+
80+
if ($throwable instanceof TransportExceptionInterface) {
81+
return true;
82+
}
83+
84+
return \in_array($response->getStatusCode(), $this->statusCodes, true);
85+
}
86+
87+
public function getWaitingTime(int $retryCount, ResponseInterface $response, \Throwable $throwable = null): int
88+
{
89+
$delay = $this->delayMilliseconds * $this->multiplier ** $retryCount;
90+
91+
if ($delay > $this->maxDelayMilliseconds && 0 !== $this->maxDelayMilliseconds) {
92+
return $this->maxDelayMilliseconds;
93+
}
94+
95+
return $delay;
96+
}
97+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpClient\Retry;
13+
14+
use Symfony\Contracts\HttpClient\ResponseInterface;
15+
16+
/**
17+
* @author Jérémy Derussé <jeremy@derusse.com>
18+
*/
19+
interface RetryStrategyInterface
20+
{
21+
public function isRetryable(int $retryCount, ResponseInterface $response, \Throwable $throwable = null): bool;
22+
23+
public function getWaitingTime(int $retryCount, ResponseInterface $response, \Throwable $throwable = null): int;
24+
}

0 commit comments

Comments
 (0)