diff --git a/README.md b/README.md index 2782f25e..6406437a 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,11 @@ $connection->getMinutelyLimitReset(); // Retrieve the timestamp for when the min ``` _Do note when you have no more minutely calls available, Exact only sends the Minutely Limit headers. So in that case, the Daily Limit headers will remain 0 until the minutely reset rolls over._ +There is basic support to `sleep` upon hitting the minutely rate limits. If you enable "Wait on minutely rate limit hit", the client will sleep until the limit is reset. Daily limits are not considered. + +```php +$connection->setWaitOnMinutelyRateLimitHit(true); +``` ### Use the library to do stuff (examples) diff --git a/composer.json b/composer.json index 2b5f4faa..d249d293 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,8 @@ ], "require": { "php": ">=7.2.0", - "guzzlehttp/guzzle": "~6.0|~7.0" + "guzzlehttp/guzzle": "~6.0|~7.0", + "ext-json": "*" }, "require-dev": { "phpunit/phpunit": "^8.5|^9.3" diff --git a/src/Picqer/Financials/Exact/Connection.php b/src/Picqer/Financials/Exact/Connection.php index 5fc6024b..e91f007b 100644 --- a/src/Picqer/Financials/Exact/Connection.php +++ b/src/Picqer/Financials/Exact/Connection.php @@ -140,6 +140,11 @@ class Connection */ protected $minutelyLimitReset; + /** + * @var bool + */ + private $waitOnMinutelyRateLimitHit = false; + /** * @return Client */ @@ -266,6 +271,7 @@ private function createRequest($method, $endpoint, $body = null, array $params = */ public function get($url, array $params = [], array $headers = []) { + $this->waitIfMinutelyRateLimitHit(); $url = $this->formatUrl($url, $url !== 'current/Me', $url == $this->nextUrl); try { @@ -289,6 +295,7 @@ public function get($url, array $params = [], array $headers = []) */ public function post($url, $body) { + $this->waitIfMinutelyRateLimitHit(); $url = $this->formatUrl($url); try { @@ -334,6 +341,7 @@ public function upload($topic, $body) */ public function put($url, $body) { + $this->waitIfMinutelyRateLimitHit(); $url = $this->formatUrl($url); try { @@ -356,6 +364,7 @@ public function put($url, $body) */ public function delete($url) { + $this->waitIfMinutelyRateLimitHit(); $url = $this->formatUrl($url); try { @@ -870,4 +879,24 @@ private function extractRateLimits(Response $response) $this->minutelyLimitRemaining = (int) $response->getHeaderLine('X-RateLimit-Minutely-Remaining'); $this->minutelyLimitReset = (int) $response->getHeaderLine('X-RateLimit-Minutely-Reset'); } + + protected function waitIfMinutelyRateLimitHit() + { + if (! $this->waitOnMinutelyRateLimitHit) { + return; + } + + $minutelyReset = $this->getMinutelyLimitReset(); + + if ($this->getMinutelyLimitRemaining() === 0 && $minutelyReset) { + // add a second for rounding differences + $resetsInSeconds = (($minutelyReset / 1000) - time()) + 1; + sleep($resetsInSeconds); + } + } + + public function setWaitOnMinutelyRateLimitHit(bool $waitOnMinutelyRateLimitHit) + { + $this->waitOnMinutelyRateLimitHit = $waitOnMinutelyRateLimitHit; + } }