Skip to content

Commit 0ddca06

Browse files
Merge pull request sendgrid#23 from budirec/feature/rate_limi
Automatically retry when rate limit is reached
2 parents e4e73bc + f3c48d4 commit 0ddca06

File tree

3 files changed

+36
-11
lines changed

3 files changed

+36
-11
lines changed

Diff for: examples/example.php

+9
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@
1818
echo $response->body();
1919
echo $response->headers();
2020

21+
// GET with auto retry on rate limit
22+
$query_params = ['limit' => 100, 'offset' => 0];
23+
$request_headers = ['X-Mock: 200'];
24+
$retryOnLimit = true;
25+
$response = $client->api_keys()->get(null, $query_params, $request_headers, $retryOnLimit);
26+
echo $response->statusCode();
27+
echo $response->body();
28+
echo $response->headers();
29+
2130
// POST
2231
$request_body = [
2332
'name' => 'My PHP API Key',

Diff for: lib/Client.php

+25-9
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,20 @@ class Client
3232
protected $curlOptions;
3333
/** @var array */
3434
private $methods;
35+
/** @var bool */
36+
private $retryOnLimit;
3537

3638
/**
3739
* Initialize the client
3840
*
39-
* @param string $host the base url (e.g. https://api.sendgrid.com)
40-
* @param array $headers global request headers
41-
* @param string $version api version (configurable)
42-
* @param array $path holds the segments of the url path
43-
* @param array $curlOptions extra options to set during curl initialization
41+
* @param string $host the base url (e.g. https://api.sendgrid.com)
42+
* @param array $headers global request headers
43+
* @param string $version api version (configurable)
44+
* @param array $path holds the segments of the url path
45+
* @param array $curlOptions extra options to set during curl initialization
46+
* @param bool $retryOnLimit set default retry on limit flag
4447
*/
45-
public function __construct($host, $headers = null, $version = null, $path = null, $curlOptions = null)
48+
public function __construct($host, $headers = null, $version = null, $path = null, $curlOptions = null, $retryOnLimit = false)
4649
{
4750
$this->host = $host;
4851
$this->headers = $headers ?: [];
@@ -51,6 +54,8 @@ public function __construct($host, $headers = null, $version = null, $path = nul
5154
$this->curlOptions = $curlOptions ?: [];
5255
// These are the supported HTTP verbs
5356
$this->methods = ['delete', 'get', 'patch', 'post', 'put'];
57+
58+
$this->retryOnLimit = $retryOnLimit;
5459
}
5560

5661
/**
@@ -134,10 +139,11 @@ private function buildUrl($queryParams = null)
134139
* @param string $url the final url to call
135140
* @param array $body request body
136141
* @param array $headers any additional request headers
142+
* @param bool $retryOnLimit should retry if rate limit is reach?
137143
*
138144
* @return Response object
139145
*/
140-
public function makeRequest($method, $url, $body = null, $headers = null)
146+
public function makeRequest($method, $url, $body = null, $headers = null, $retryOnLimit = false)
141147
{
142148
$curl = curl_init($url);
143149

@@ -169,8 +175,17 @@ public function makeRequest($method, $url, $body = null, $headers = null)
169175
$responseHeaders = array_map('trim', $responseHeaders);
170176

171177
curl_close($curl);
178+
179+
$response = new Response($statusCode, $responseBody, $responseHeaders);
180+
181+
if ($statusCode == 429 && $retryOnLimit) {
182+
$headers = $response->headers(true);
183+
$sleepDurations = $headers['X-Ratelimit-Reset'] - time();
184+
sleep($sleepDurations > 0 ? $sleepDurations : 0);
185+
return $this->makeRequest($method, $url, $body, $headers, false);
186+
}
172187

173-
return new Response($statusCode, $responseBody, $responseHeaders);
188+
return $response;
174189
}
175190

176191
/**
@@ -211,7 +226,8 @@ public function __call($name, $args)
211226
$queryParams = isset($args[1]) ? $args[1] : null;
212227
$url = $this->buildUrl($queryParams);
213228
$headers = isset($args[2]) ? $args[2] : null;
214-
return $this->makeRequest($name, $url, $body, $headers);
229+
$retryOnLimit = isset($args[3]) ? $args[3] : $this->retryOnLimit;
230+
return $this->makeRequest($name, $url, $body, $headers, $retryOnLimit);
215231
}
216232

217233
return $this->_($name);

Diff for: test/unit/MockClient.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ class MockClient extends Client
1010
protected $requestHeaders;
1111
protected $url;
1212

13-
public function makeRequest($method, $url, $requestBody = null, $requestHeaders = null)
13+
public function makeRequest($method, $url, $requestBody = null, $requestHeaders = null, $retryOnLimit = false)
1414
{
1515
$this->requestBody = $requestBody;
1616
$this->requestHeaders = $requestHeaders;
1717
$this->url = $url;
1818
return $this;
1919
}
20-
}
20+
}

0 commit comments

Comments
 (0)