Fix retry to add a small pause between retries after the second one, refs #10716
parent
1f75af6f89
commit
da322643d6
|
@ -256,7 +256,7 @@ parameters:
|
||||||
path: ../src/Composer/Util/Http/CurlDownloader.php
|
path: ../src/Composer/Util/Http/CurlDownloader.php
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Property Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:\\$jobs \\(array\\<array\\{url\\: string, origin\\: string, attributes\\: array\\{retryAuthFailure\\: bool, redirects\\: int, retries\\: int, storeAuth\\: bool\\}, options\\: array, progress\\: array, curlHandle\\: resource, filename\\: string\\|null, headerHandle\\: resource, \\.\\.\\.\\}\\>\\) does not accept non\\-empty\\-array\\<array\\{url\\: string, origin\\: string, attributes\\: array\\{retryAuthFailure\\: bool, redirects\\: int, retries\\: int, storeAuth\\: bool\\}, options\\: array, progress\\: array, curlHandle\\: CurlHandle\\|resource, filename\\: string\\|null, headerHandle\\: resource, \\.\\.\\.\\}\\>\\.$#"
|
message: "#^Property Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:\\$jobs \\(array\\<array\\{url\\: string, origin\\: string, attributes\\: array\\{retryAuthFailure\\: bool, redirects\\: int\\<0, max\\>, retries\\: int\\<0, max\\>, storeAuth\\: 'prompt'\\|bool\\}, options\\: array, progress\\: array, curlHandle\\: resource, filename\\: string\\|null, headerHandle\\: resource, \\.\\.\\.\\}\\>\\) does not accept non\\-empty\\-array\\<array\\{url\\: string, origin\\: string, attributes\\: array\\{retryAuthFailure\\: bool, redirects\\: int\\<0, max\\>, retries\\: int\\<0, max\\>, storeAuth\\: 'prompt'\\|bool\\}, options\\: array, progress\\: array, curlHandle\\: CurlHandle\\|resource, filename\\: string\\|null, headerHandle\\: resource, \\.\\.\\.\\}\\>\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
path: ../src/Composer/Util/Http/CurlDownloader.php
|
path: ../src/Composer/Util/Http/CurlDownloader.php
|
||||||
|
|
||||||
|
|
|
@ -4813,16 +4813,6 @@ parameters:
|
||||||
count: 3
|
count: 3
|
||||||
path: ../src/Composer/Util/Http/CurlDownloader.php
|
path: ../src/Composer/Util/Http/CurlDownloader.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:isAuthenticatedRetryNeeded\\(\\) should return array\\{retry\\: bool, storeAuth\\: bool\\|string\\} but returns array\\{retry\\: bool, storeAuth\\: bool\\|string\\}\\|null\\.$#"
|
|
||||||
count: 2
|
|
||||||
path: ../src/Composer/Util/Http/CurlDownloader.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Offset 'retry' does not exist on array\\{retry\\: bool, storeAuth\\: bool\\|string\\}\\|null\\.$#"
|
|
||||||
count: 2
|
|
||||||
path: ../src/Composer/Util/Http/CurlDownloader.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Only booleans are allowed in &&, int given on the right side\\.$#"
|
message: "#^Only booleans are allowed in &&, int given on the right side\\.$#"
|
||||||
count: 2
|
count: 2
|
||||||
|
@ -4938,11 +4928,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: ../src/Composer/Util/Http/CurlDownloader.php
|
path: ../src/Composer/Util/Http/CurlDownloader.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Parameter \\#3 \\$attributes of method Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:restartJob\\(\\) expects array\\{retryAuthFailure\\?\\: bool, redirects\\?\\: int, storeAuth\\?\\: bool\\}, array\\{storeAuth\\: bool\\|string\\} given\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: ../src/Composer/Util/Http/CurlDownloader.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Parameter \\#3 \\$errorMessage of method Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:failResponse\\(\\) expects string, string\\|null given\\.$#"
|
message: "#^Parameter \\#3 \\$errorMessage of method Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:failResponse\\(\\) expects string, string\\|null given\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
@ -4954,7 +4939,7 @@ parameters:
|
||||||
path: ../src/Composer/Util/Http/CurlDownloader.php
|
path: ../src/Composer/Util/Http/CurlDownloader.php
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Property Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:\\$jobs \\(array\\<array\\{url\\: string, origin\\: string, attributes\\: array\\{retryAuthFailure\\: bool, redirects\\: int, retries\\: int, storeAuth\\: bool\\}, options\\: array, progress\\: array, curlHandle\\: resource, filename\\: string\\|null, headerHandle\\: resource, \\.\\.\\.\\}\\>\\) does not accept non\\-empty\\-array\\<array\\{url\\: string, origin\\: string, attributes\\: array\\{retryAuthFailure\\: bool, redirects\\: int, retries\\: int, storeAuth\\: bool\\}, options\\: array, progress\\: array, curlHandle\\: resource, filename\\: string\\|null, headerHandle\\: resource, \\.\\.\\.\\}\\>\\.$#"
|
message: "#^Property Composer\\\\Util\\\\Http\\\\CurlDownloader\\:\\:\\$jobs \\(array\\<array\\{url\\: string, origin\\: string, attributes\\: array\\{retryAuthFailure\\: bool, redirects\\: int\\<0, max\\>, retries\\: int\\<0, max\\>, storeAuth\\: 'prompt'\\|bool\\}, options\\: array, progress\\: array, curlHandle\\: resource, filename\\: string\\|null, headerHandle\\: resource, \\.\\.\\.\\}\\>\\) does not accept non\\-empty\\-array\\<array\\{url\\: string, origin\\: string, attributes\\: array\\{retryAuthFailure\\: bool, redirects\\: int\\<0, max\\>, retries\\: int\\<0, max\\>, storeAuth\\: 'prompt'\\|bool\\}, options\\: array, progress\\: array, curlHandle\\: resource, filename\\: string\\|null, headerHandle\\: resource, \\.\\.\\.\\}\\>\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
path: ../src/Composer/Util/Http/CurlDownloader.php
|
path: ../src/Composer/Util/Http/CurlDownloader.php
|
||||||
|
|
||||||
|
@ -5363,16 +5348,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: ../src/Composer/Util/RemoteFilesystem.php
|
path: ../src/Composer/Util/RemoteFilesystem.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Offset 'retry' does not exist on array\\{retry\\: bool, storeAuth\\: bool\\|string\\}\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: ../src/Composer/Util/RemoteFilesystem.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Offset 'storeAuth' does not exist on array\\{retry\\: bool, storeAuth\\: bool\\|string\\}\\|null\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: ../src/Composer/Util/RemoteFilesystem.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Only booleans are allowed in &&, bool\\|string given on the left side\\.$#"
|
message: "#^Only booleans are allowed in &&, bool\\|string given on the left side\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
|
@ -37,7 +37,7 @@ class AuthHelper
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $origin
|
* @param string $origin
|
||||||
* @param string|bool $storeAuth
|
* @param 'prompt'|bool $storeAuth
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
@ -79,11 +79,11 @@ class AuthHelper
|
||||||
* @param int $statusCode HTTP status code that triggered this call
|
* @param int $statusCode HTTP status code that triggered this call
|
||||||
* @param string|null $reason a message/description explaining why this was called
|
* @param string|null $reason a message/description explaining why this was called
|
||||||
* @param string[] $headers
|
* @param string[] $headers
|
||||||
* @return array|null containing retry (bool) and storeAuth (string|bool) keys, if retry is true the request should be
|
* @return array containing retry (bool) and storeAuth (string|bool) keys, if retry is true the request should be
|
||||||
* retried, if storeAuth is true then on a successful retry the authentication should be persisted to auth.json
|
* retried, if storeAuth is true then on a successful retry the authentication should be persisted to auth.json
|
||||||
* @phpstan-return ?array{retry: bool, storeAuth: string|bool}
|
* @phpstan-return array{retry: bool, storeAuth: 'prompt'|bool}
|
||||||
*/
|
*/
|
||||||
public function promptAuthIfNeeded(string $url, string $origin, int $statusCode, ?string $reason = null, array $headers = array()): ?array
|
public function promptAuthIfNeeded(string $url, string $origin, int $statusCode, ?string $reason = null, array $headers = array()): array
|
||||||
{
|
{
|
||||||
$storeAuth = false;
|
$storeAuth = false;
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ class AuthHelper
|
||||||
} else {
|
} else {
|
||||||
// 404s are only handled for github
|
// 404s are only handled for github
|
||||||
if ($statusCode === 404) {
|
if ($statusCode === 404) {
|
||||||
return null;
|
return ['retry' => false, 'storeAuth' => false];
|
||||||
}
|
}
|
||||||
|
|
||||||
// fail if the console is not interactive
|
// fail if the console is not interactive
|
||||||
|
|
|
@ -27,7 +27,7 @@ use React\Promise\Promise;
|
||||||
* @internal
|
* @internal
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
* @author Nicolas Grekas <p@tchwork.com>
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
* @phpstan-type Attributes array{retryAuthFailure: bool, redirects: int, retries: int, storeAuth: bool}
|
* @phpstan-type Attributes array{retryAuthFailure: bool, redirects: int<0, max>, retries: int<0, max>, storeAuth: 'prompt'|bool}
|
||||||
* @phpstan-type Job array{url: string, origin: string, attributes: Attributes, options: mixed[], progress: mixed[], curlHandle: resource, filename: string|null, headerHandle: resource, bodyHandle: resource, resolve: callable, reject: callable}
|
* @phpstan-type Job array{url: string, origin: string, attributes: Attributes, options: mixed[], progress: mixed[], curlHandle: resource, filename: string|null, headerHandle: resource, bodyHandle: resource, resolve: callable, reject: callable}
|
||||||
*/
|
*/
|
||||||
class CurlDownloader
|
class CurlDownloader
|
||||||
|
@ -152,7 +152,7 @@ class CurlDownloader
|
||||||
* @param mixed[] $options
|
* @param mixed[] $options
|
||||||
* @param null|string $copyTo
|
* @param null|string $copyTo
|
||||||
*
|
*
|
||||||
* @param array{retryAuthFailure?: bool, redirects?: int, retries?: int, storeAuth?: bool} $attributes
|
* @param array{retryAuthFailure?: bool, redirects?: int<0, max>, retries?: int<0, max>, storeAuth?: 'prompt'|bool} $attributes
|
||||||
*
|
*
|
||||||
* @return int internal job id
|
* @return int internal job id
|
||||||
*/
|
*/
|
||||||
|
@ -177,6 +177,7 @@ class CurlDownloader
|
||||||
throw new \RuntimeException('Failed to open a temp stream to store curl headers');
|
throw new \RuntimeException('Failed to open a temp stream to store curl headers');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($copyTo) {
|
if ($copyTo) {
|
||||||
$errorMessage = '';
|
$errorMessage = '';
|
||||||
// @phpstan-ignore-next-line
|
// @phpstan-ignore-next-line
|
||||||
|
@ -363,7 +364,7 @@ class CurlDownloader
|
||||||
) && $job['attributes']['retries'] < $this->maxRetries
|
) && $job['attributes']['retries'] < $this->maxRetries
|
||||||
) {
|
) {
|
||||||
$this->io->writeError('Retrying ('.($job['attributes']['retries'] + 1).') ' . Url::sanitize($job['url']) . ' due to curl error '. $errno, true, IOInterface::DEBUG);
|
$this->io->writeError('Retrying ('.($job['attributes']['retries'] + 1).') ' . Url::sanitize($job['url']) . ' due to curl error '. $errno, true, IOInterface::DEBUG);
|
||||||
$this->restartJob($job, $job['url'], array('retries' => $job['attributes']['retries'] + 1));
|
$this->restartJobWithDelay($job, $job['url'], array('retries' => $job['attributes']['retries'] + 1));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,14 +428,14 @@ class CurlDownloader
|
||||||
&& $job['attributes']['retries'] < $this->maxRetries
|
&& $job['attributes']['retries'] < $this->maxRetries
|
||||||
) {
|
) {
|
||||||
$this->io->writeError('Retrying ('.($job['attributes']['retries'] + 1).') ' . Url::sanitize($job['url']) . ' due to status code '. $statusCode, true, IOInterface::DEBUG);
|
$this->io->writeError('Retrying ('.($job['attributes']['retries'] + 1).') ' . Url::sanitize($job['url']) . ' due to status code '. $statusCode, true, IOInterface::DEBUG);
|
||||||
$this->restartJob($job, $job['url'], array('retries' => $job['attributes']['retries'] + 1));
|
$this->restartJobWithDelay($job, $job['url'], array('retries' => $job['attributes']['retries'] + 1));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw $this->failResponse($job, $response, $response->getStatusMessage());
|
throw $this->failResponse($job, $response, $response->getStatusMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($job['attributes']['storeAuth']) {
|
if ($job['attributes']['storeAuth'] !== false) {
|
||||||
$this->authHelper->storeAuth($job['origin'], $job['attributes']['storeAuth']);
|
$this->authHelper->storeAuth($job['origin'], $job['attributes']['storeAuth']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,8 +525,8 @@ class CurlDownloader
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Job $job
|
* @param Job $job
|
||||||
* @return array{retry: bool, storeAuth: string|bool}
|
* @return array{retry: bool, storeAuth: 'prompt'|bool}
|
||||||
*/
|
*/
|
||||||
private function isAuthenticatedRetryNeeded(array $job, Response $response): array
|
private function isAuthenticatedRetryNeeded(array $job, Response $response): array
|
||||||
{
|
{
|
||||||
|
@ -578,7 +579,7 @@ class CurlDownloader
|
||||||
* @param Job $job
|
* @param Job $job
|
||||||
* @param string $url
|
* @param string $url
|
||||||
*
|
*
|
||||||
* @param array{retryAuthFailure?: bool, redirects?: int, storeAuth?: bool} $attributes
|
* @param array{retryAuthFailure?: bool, redirects?: int<0, max>, storeAuth?: 'prompt'|bool, retries?: int<1, max>} $attributes
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
@ -594,6 +595,25 @@ class CurlDownloader
|
||||||
$this->initDownload($job['resolve'], $job['reject'], $origin, $url, $job['options'], $job['filename'], $attributes);
|
$this->initDownload($job['resolve'], $job['reject'], $origin, $url, $job['options'], $job['filename'], $attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Job $job
|
||||||
|
* @param string $url
|
||||||
|
*
|
||||||
|
* @param array{retryAuthFailure?: bool, redirects?: int<0, max>, storeAuth?: 'prompt'|bool, retries: int<1, max>} $attributes
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function restartJobWithDelay(array $job, string $url, array $attributes): void
|
||||||
|
{
|
||||||
|
if ($attributes['retries'] >= 3) {
|
||||||
|
usleep(500000); // half a second delay for 3rd retry and beyond
|
||||||
|
} elseif ($attributes['retries'] >= 2) {
|
||||||
|
usleep(100000); // 100ms delay for 2nd retry
|
||||||
|
} // no sleep for the first retry
|
||||||
|
|
||||||
|
$this->restartJob($job, $url, $attributes);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Job $job
|
* @param Job $job
|
||||||
* @param string $errorMessage
|
* @param string $errorMessage
|
||||||
|
|
Loading…
Reference in New Issue