diff --git a/src/Client/HttpClient.php b/src/Client/HttpClient.php index feb23e14..a040ffb1 100644 --- a/src/Client/HttpClient.php +++ b/src/Client/HttpClient.php @@ -73,7 +73,7 @@ public function sendRequest(string $httpMethod, $uri, array $headers = [], $body { $request = $this->prepareRequest($httpMethod, $uri, $headers, $body); - $response = $this->httpClient->sendRequest($request); + $response = $this->retry($this->httpClient->sendRequest($request), $request); return $this->httpExceptionHandler->transformResponseToException($request, $response); } @@ -88,4 +88,17 @@ public function sendAsync( return $this->httpClient->sendAsyncRequest($request); } + + private function retry(ResponseInterface $response, RequestInterface $request, int $retryDelay = 2): ResponseInterface + { + if ($this->options->canRetry() && HttpClient::HTTP_TOO_MANY_REQUESTS === $response->getStatusCode()) { + $retry = 0; + while ($this->options->getMaxRetry() > $retry && HttpClient::HTTP_TOO_MANY_REQUESTS === $response->getStatusCode()) { + usleep($retryDelay * 1000); + $response = $this->httpClient->sendRequest($request); + $retry++; + } + } + return $response; + } } diff --git a/src/Client/Options.php b/src/Client/Options.php index ff53ca9f..cc1e38dc 100644 --- a/src/Client/Options.php +++ b/src/Client/Options.php @@ -9,7 +9,7 @@ class Options { private function __construct( - private array $options + private array $options, ) { } @@ -19,8 +19,12 @@ public static function fromArray(array $options): self $resolver->setDefaults([ 'headers' => [], + 'retry' => false, + 'max-retry' => 5, ]); $resolver->setAllowedTypes('headers', 'string[]'); + $resolver->setAllowedTypes('retry', 'bool'); + $resolver->setAllowedTypes('max-retry', 'int'); $options = $resolver->resolve($options); @@ -39,4 +43,14 @@ public function getHeaders(): array { return $this->options['headers']; } + + public function getMaxRetry(): int + { + return $this->options['max-retry']; + } + + public function canRetry(): bool + { + return $this->options['retry']; + } } diff --git a/tests/Api/AkeneoPimClientBuilderTest.php b/tests/Api/AkeneoPimClientBuilderTest.php new file mode 100644 index 00000000..15fd1f8e --- /dev/null +++ b/tests/Api/AkeneoPimClientBuilderTest.php @@ -0,0 +1,50 @@ +server->setResponseOfPath( + '/' . ProductApi::PRODUCTS_URI, + new ResponseStack( + new Response('', [], 429), + new Response('', [], 429), + new Response('', [], 429), + new Response('', [], 429), + new Response('', [], 201), + ) + ); + + $api = $this->createClientByPassword()->getProductApi(); + $response = $api->create('new_shoes', []); + + Assert::assertSame(201, $response); + } + + protected function createClientByPassword(): AkeneoPimClientInterface + { + $clientBuilder = new AkeneoPimClientBuilder($this->server->getServerRoot(), [ + 'retry' => true, + 'max-retry' => 5, + ]); + + return $clientBuilder->buildAuthenticatedByPassword( + 'client_id', + 'secret', + 'username', + 'password' + ); + } +}