-
Notifications
You must be signed in to change notification settings - Fork 15
/
RetrySender.php
83 lines (68 loc) · 2.52 KB
/
RetrySender.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<?php
namespace SmartyStreets\PhpSdk;
include_once('Sender.php');
require_once('Exceptions/TooManyRequestsException.php');
use SmartyStreets\PhpSdk\Exceptions\BadGatewayException;
use SmartyStreets\PhpSdk\Exceptions\GatewayTimeoutException;
use SmartyStreets\PhpSdk\Exceptions\InternalServerErrorException;
use SmartyStreets\PhpSdk\Exceptions\MustRetryException;
use SmartyStreets\PhpSdk\Exceptions\RequestTimeoutException;
use SmartyStreets\PhpSdk\Exceptions\ServiceUnavailableException;
use SmartyStreets\PhpSdk\Exceptions\TooManyRequestsException;
class RetrySender implements Sender
{
const MAX_BACKOFF_DURATION = 10;
const STATUS_TOO_MANY_REQUESTS = 429;
const STATUS_TO_RETRY = [408, 429, 500, 502, 503, 504];
private $inner,
$maxRetries,
$sleeper,
$logger;
public function __construct($maxRetries, Sleeper $sleeper, Logger $logger, Sender $inner)
{
$this->inner = $inner;
$this->sleeper = $sleeper;
$this->logger = $logger;
$this->maxRetries = $maxRetries;
}
public function send(Request $request)
{
for ($i = 0; $i <= $this->maxRetries; $i++) {
$response = $this->trySend($request, $i);
if ($response!= null && !in_array($response->getStatusCode(), self::STATUS_TO_RETRY)){
return $response;
}
}
return null;
}
private function trySend(Request $request, $attempt)
{
try {
return $this->inner->send($request);
} catch (TooManyRequestsException $ex) {
$this->backoff($ex->getHeader());
return null;
} catch (\Exception $ex) {
if (($ex instanceof MustRetryException || $ex instanceof InternalServerErrorException || $ex instanceof ServiceUnavailableException || $ex instanceof GatewayTimeoutException || $ex instanceof RequestTimeoutException || $ex instanceof BadGatewayException) && $attempt < $this->maxRetries) {
$this->backoff(self::MAX_BACKOFF_DURATION);
} else {
echo $ex->getCode() . "\n";
throw $ex;
}
}
return null;
}
public function getInner()
{
return $this->inner;
}
public function getMaxRetries()
{
return $this->maxRetries;
}
private function backoff($backoffDuration)
{
$this->logger->log("There was an error processing the request. Retrying in " . $backoffDuration . " seconds...");
$this->sleeper->sleep($backoffDuration);
}
}