Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PLENTY-489-retry-requests-with-exceptions #95

Merged
merged 11 commits into from
May 27, 2024
2 changes: 2 additions & 0 deletions .env.test.example
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@ EXPORT_DIR=/tmp/rest-exporter/var/export
LOG_DIR=/tmp/rest-exporter/var/log

ACCOUNT_PAT=""

FAILED_REQUEST_SLEEP_TIMER=1
32 changes: 27 additions & 5 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@
use FINDOLOGIC\PlentyMarketsRestExporter\Debug\DummyDebugger;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\AuthorizationException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\CriticalException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\CustomerException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\Retry\CustomerException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\PermissionException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\Retry\EmptyResponseException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\Retry\RetryableException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\RetryLimitException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\ThrottlingException;
use FINDOLOGIC\PlentyMarketsRestExporter\Logger\DummyLogger;
use FINDOLOGIC\PlentyMarketsRestExporter\Request\Request;
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7\Request as GuzzleRequest;
use GuzzleHttp\Psr7\Uri;
use GuzzleHttp\RequestOptions;
Expand Down Expand Up @@ -85,17 +88,35 @@ public function __construct(
* @throws ThrottlingException
* @throws GuzzleException
* @throws CriticalException
* @throws RetryLimitException
*/
public function send(Request $request): ResponseInterface
{
$this->handleRateLimit();
$this->handleLogin();

$request = $request->withUri($this->buildRequestUri($request->getUri()->__toString()));
$response = $this->sendRequest($request, $request->getParams());
$this->handleResponse($request, $response);
$endpoint = $request->getUri()->__toString();
$request = $request->withUri($this->buildRequestUri($endpoint));
do {
try {
$response = $this->sendRequest($request, $request->getParams());
$this->handleResponse($request, $response);

return $response;
} catch (RetryableException | RequestException $e) {
$this->customerLogger->error($e->getMessage());
$request->incrementRetryCounter();

sleep((int)Utils::env('FAILED_REQUEST_SLEEP_TIMER', 60));

$this->customerLogger->debug(sprintf(
'Retrying failed request. Attempt number %s.',
(string) $request->getRetryCounter()
));
}
} while (!$request->isRetryLimitReached());

return $response;
throw new RetryLimitException('Maximum retry limit reached without success');
}

/**
Expand All @@ -120,6 +141,7 @@ private function sendRequest(RequestInterface $request, array $params = null): R
$request,
$this->getRequestOptions($request, $params)
);

$this->lastResponse = $response;

return $response;
Expand Down
2 changes: 1 addition & 1 deletion src/Command/GenerateTokenCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use Exception;
use FINDOLOGIC\PlentyMarketsRestExporter\Client;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\AuthorizationException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\CustomerException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\Retry\CustomerException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\PermissionException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\Retry\EmptyResponseException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\ThrottlingException;
Expand Down
4 changes: 3 additions & 1 deletion src/Exception/PermissionException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace FINDOLOGIC\PlentyMarketsRestExporter\Exception;

class PermissionException extends CustomerException
use Exception;

class PermissionException extends Exception
{
}
11 changes: 11 additions & 0 deletions src/Exception/Retry/CustomerException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace FINDOLOGIC\PlentyMarketsRestExporter\Exception\Retry;

use FINDOLOGIC\PlentyMarketsRestExporter\Exception\Retry\RetryableException;

class CustomerException extends RetryableException
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@

use Exception;

class CustomerException extends Exception
class RetryLimitException extends Exception
{
}
2 changes: 1 addition & 1 deletion src/Exporter/Exporter.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use FINDOLOGIC\PlentyMarketsRestExporter\Config;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\AuthorizationException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\CriticalException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\CustomerException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\Retry\CustomerException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\PermissionException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\Retry\EmptyResponseException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\ThrottlingException;
Expand Down
2 changes: 1 addition & 1 deletion src/RegistryService.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use FINDOLOGIC\PlentyMarketsRestExporter\Definition\PropertyOptionType;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\AuthorizationException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\CriticalException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\CustomerException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\Retry\CustomerException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\PermissionException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\Retry\EmptyResponseException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\ThrottlingException;
Expand Down
18 changes: 18 additions & 0 deletions src/Request/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@

abstract class Request extends GuzzleRequest
{
private const RETRY_LIMIT = 5;

protected array $params = [];
private int $retryCounter = 0;

public function __construct(
string $method,
Expand All @@ -28,4 +31,19 @@ public function getParams(): array
{
return $this->params;
}

public function getRetryCounter(): int
{
return $this->retryCounter;
}

public function incrementRetryCounter(): void
{
$this->retryCounter++;
}

public function isRetryLimitReached(): bool
{
return $this->retryCounter >= self::RETRY_LIMIT;
}
}
2 changes: 1 addition & 1 deletion src/Utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use FINDOLOGIC\Export\Helpers\DataHelper;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\AuthorizationException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\CriticalException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\CustomerException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\Retry\CustomerException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\PermissionException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\Retry\EmptyResponseException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\ThrottlingException;
Expand Down
31 changes: 18 additions & 13 deletions tests/ClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
use FINDOLOGIC\PlentyMarketsRestExporter\Config;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\AuthorizationException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\CriticalException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\CustomerException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\Retry\CustomerException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\PermissionException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\Retry\EmptyResponseException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\RetryLimitException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\ThrottlingException;
use FINDOLOGIC\PlentyMarketsRestExporter\Request\CategoryRequest;
use FINDOLOGIC\PlentyMarketsRestExporter\Request\Request;
Expand Down Expand Up @@ -95,6 +96,7 @@ public function badResponseProvider(): array
'response' => new GuzzleResponse(401, [], 'OOF you are not logged in bro...'),
'expectedException' => AuthorizationException::class,
'expectedExceptionMessage' => 'The REST client is not logged in.',
'expectedCallTimes' => 2
TobiasGraml11 marked this conversation as resolved.
Show resolved Hide resolved
],
'response with status code 403' => [
'request' => new CategoryRequest(1234),
Expand All @@ -104,30 +106,28 @@ public function badResponseProvider(): array
'The REST client does not have access rights for method with URI "%s"',
$requestUri
),
'expectedCallTimes' => 2
],
'response with status code 429' => [
'request' => new CategoryRequest(1234),
'response' => new GuzzleResponse(429, [], 'You have reached your rate limit :('),
'expectedException' => ThrottlingException::class,
'expectedExceptionMessage' => 'Throttling limit reached.',
'expectedCallTimes' => 2
],
'response with status code 200 but empty response' => [
'request' => new CategoryRequest(1234),
'response' => new GuzzleResponse(200, [], ''),
'expectedException' => EmptyResponseException::class,
'expectedExceptionMessage' => sprintf(
'The API for URI "%s" responded with an empty response',
$requestUri
),
'expectedException' => RetryLimitException::class,
'expectedExceptionMessage' => 'Maximum retry limit reached without success',
'expectedCallTimes' => 6
],
'response with unknown status code 400' => [
'request' => new CategoryRequest(1234),
'response' => new GuzzleResponse(400, [], 'Unprocessable entity!'),
'expectedException' => CustomerException::class,
'expectedExceptionMessage' => sprintf(
'Could not reach API method with URI "%s". Status code was 400.',
$requestUri
),
'expectedException' => RetryLimitException::class,
'expectedExceptionMessage' => 'Maximum retry limit reached without success',
'expectedCallTimes' => 6
],
];
}
Expand All @@ -139,17 +139,22 @@ public function testExceptionsAreThrownIfResponseHasBadStatusCodes(
Request $request,
GuzzleResponse $response,
string $expectedException,
string $expectedExceptionMessage
string $expectedExceptionMessage,
int $expectedCallTimes
): void {
$this->expectException($expectedException);
$this->expectExceptionMessage($expectedExceptionMessage);

$client = $this->getDefaultClient();

$this->guzzleClientMock->expects($this->exactly(2))
$this->guzzleClientMock->expects($this->exactly($expectedCallTimes))
->method('send')
->willReturnOnConsecutiveCalls(
$this->getMockResponse('LoginResponse/response.json'),
$response,
$response,
$response,
$response,
$response
);

Expand Down
2 changes: 1 addition & 1 deletion tests/RegistryServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use FINDOLOGIC\PlentyMarketsRestExporter\Client;
use FINDOLOGIC\PlentyMarketsRestExporter\Config;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\AuthorizationException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\CustomerException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\Retry\CustomerException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\PermissionException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\Retry\EmptyResponseException;
use FINDOLOGIC\PlentyMarketsRestExporter\Exception\ThrottlingException;
Expand Down
Loading