Skip to content

Commit 181906e

Browse files
committed
Merge branch 'main' into release/v1.5.3
2 parents 18ad350 + 5e3403a commit 181906e

File tree

3 files changed

+72
-14
lines changed

3 files changed

+72
-14
lines changed

src/BigCommerce/Api/Generic/BatchUpdateResource.php

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,20 @@
44

55
use BigCommerce\ApiV3\Client;
66
use BigCommerce\ApiV3\ResponseModels\PaginatedResponse;
7+
use GuzzleHttp\Exception\RequestException;
78
use GuzzleHttp\RequestOptions;
9+
use Psr\Http\Client\RequestExceptionInterface;
810
use Psr\Http\Message\ResponseInterface;
11+
use RuntimeException;
912

1013
trait BatchUpdateResource
1114
{
1215
abstract public function batchUpdate(array $resources): PaginatedResponse;
1316
abstract protected function multipleResourcesEndpoint(): string;
1417
abstract public function getClient(): Client;
1518

19+
private int $maxRetries = 0;
20+
1621
protected function maxBatchSize(): int
1722
{
1823
return 10;
@@ -21,20 +26,46 @@ protected function maxBatchSize(): int
2126
/**
2227
* @param array $resources
2328
* @return ResponseInterface[]
29+
* @throws RequestExceptionInterface
2430
*/
2531
protected function batchUpdateResource(array $resources): array
2632
{
2733
$chunks = array_chunk($resources, $this->maxBatchSize());
28-
$responses = [];
29-
foreach ($chunks as $chunk) {
30-
$responses[] = $this->getClient()->getRestClient()->put(
31-
$this->multipleResourcesEndpoint(),
32-
[
33-
RequestOptions::JSON => $chunk,
34-
]
35-
);
34+
return array_map(fn($chunk) => $this->putRequestWithRetries($chunk), $chunks);
35+
}
36+
37+
private function putRequestWithRetries($data): ResponseInterface
38+
{
39+
$retriesRemaining = $this->getMaxRetries() + 1;
40+
41+
while ($retriesRemaining-- > 0) {
42+
try {
43+
return $this->getClient()->getRestClient()->put(
44+
$this->multipleResourcesEndpoint(),
45+
[
46+
RequestOptions::JSON => $data,
47+
]
48+
);
49+
} catch (\Exception $exception) {
50+
if (!in_array($exception->getCode(), $this->retryOnErrorCodes()) || $retriesRemaining <= 0) {
51+
throw $exception;
52+
}
53+
}
3654
}
55+
}
3756

38-
return $responses;
57+
protected function retryOnErrorCodes(): array
58+
{
59+
return [500, 502, 503, 504];
60+
}
61+
62+
public function getMaxRetries(): int
63+
{
64+
return $this->maxRetries;
65+
}
66+
67+
public function setMaxRetries(int $maxRetries): void
68+
{
69+
$this->maxRetries = $maxRetries;
3970
}
4071
}

tests/BigCommerce/Api/Redirects/RedirectsApiTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use BigCommerce\ApiV3\ResourceModels\Redirect\Redirect;
66
use BigCommerce\ApiV3\ResourceModels\Redirect\RedirectTo;
77
use BigCommerce\Tests\BigCommerceApiTest;
8+
use GuzzleHttp\Exception\RequestException;
89

910
class RedirectsApiTest extends BigCommerceApiTest
1011
{
@@ -38,4 +39,23 @@ public function testCanDeleteRedirects()
3839
$this->getApi()->redirects()->delete([1, 2, 3]);
3940
$this->assertEquals('storefront/redirects', $this->getLastRequestPath());
4041
}
42+
43+
public function testRetryOnError()
44+
{
45+
$this->setReturnData('blank.json', 503, [], 3);
46+
$redirect = new Redirect();
47+
$redirect->from_path = '/old-url';
48+
$redirect->site_id = 0;
49+
$redirect->toProduct(1);
50+
51+
//https://httpbin.org/status/502
52+
$redirectsApi = $this->getApi()->redirects();
53+
$redirectsApi->setMaxRetries(2);
54+
try {
55+
$redirectsApi->upsert([$redirect]);
56+
$this->assertFalse(true, 'Exception not raised');
57+
} catch (RequestException $e) {
58+
$this->assertCount(3, $this->getRequestHistory());
59+
}
60+
}
4161
}

tests/BigCommerce/BigCommerceApiTest.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,18 @@ protected function setUp(): void
3737
);
3838
}
3939

40-
protected function setReturnData(string $filename, int $statusCode = 200, array $headers = []): void
41-
{
42-
$mock = new MockHandler([
43-
new Response($statusCode, $headers, file_get_contents(self::RESPONSES_PATH . $filename)),
44-
]);
40+
protected function setReturnData(
41+
string $filename,
42+
int $statusCode = 200,
43+
array $headers = [],
44+
int $numberOfResponses = 1
45+
): void {
46+
$responses = [];
47+
for ($i = 1; $i <= $numberOfResponses; $i++) {
48+
$responses[] = new Response($statusCode, $headers, file_get_contents(self::RESPONSES_PATH . $filename));
49+
}
50+
51+
$mock = new MockHandler($responses);
4552

4653
$handlerStack = HandlerStack::create($mock);
4754
$handlerStack->push(Middleware::history($this->container));

0 commit comments

Comments
 (0)