Skip to content

Commit

Permalink
Fix retry to add a small pause between retries after the second one, …
Browse files Browse the repository at this point in the history
  • Loading branch information
Seldaek authored and emahorvat52 committed Jan 18, 2023
1 parent e9b3b19 commit 7f90d91
Showing 1 changed file with 28 additions and 8 deletions.
36 changes: 28 additions & 8 deletions src/Composer/Util/Http/CurlDownloader.php
Expand Up @@ -27,7 +27,7 @@
* @internal
* @author Jordi Boggiano <j.boggiano@seld.be>
* @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}
*/
class CurlDownloader
Expand Down Expand Up @@ -152,7 +152,7 @@ public function download(callable $resolve, callable $reject, string $origin, st
* @param mixed[] $options
* @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
*/
Expand All @@ -177,6 +177,7 @@ private function initDownload(callable $resolve, callable $reject, string $origi
throw new \RuntimeException('Failed to open a temp stream to store curl headers');
}


if ($copyTo) {
$errorMessage = '';
// @phpstan-ignore-next-line
Expand Down Expand Up @@ -363,7 +364,7 @@ public function tick(): void
) && $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->restartJob($job, $job['url'], array('retries' => $job['attributes']['retries'] + 1));
$this->restartJobWithDelay($job, $job['url'], array('retries' => $job['attributes']['retries'] + 1));
continue;
}

Expand Down Expand Up @@ -427,14 +428,14 @@ public function tick(): void
&& $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->restartJob($job, $job['url'], array('retries' => $job['attributes']['retries'] + 1));
$this->restartJobWithDelay($job, $job['url'], array('retries' => $job['attributes']['retries'] + 1));
continue;
}

throw $this->failResponse($job, $response, $response->getStatusMessage());
}

if ($job['attributes']['storeAuth']) {
if ($job['attributes']['storeAuth'] !== false) {
$this->authHelper->storeAuth($job['origin'], $job['attributes']['storeAuth']);
}

Expand Down Expand Up @@ -524,8 +525,8 @@ private function handleRedirect(array $job, Response $response): string
}

/**
* @param Job $job
* @return array{retry: bool, storeAuth: string|bool}
* @param Job $job
* @return array{retry: bool, storeAuth: 'prompt'|bool}
*/
private function isAuthenticatedRetryNeeded(array $job, Response $response): array
{
Expand Down Expand Up @@ -578,7 +579,7 @@ private function isAuthenticatedRetryNeeded(array $job, Response $response): arr
* @param Job $job
* @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
*/
Expand All @@ -594,6 +595,25 @@ private function restartJob(array $job, string $url, array $attributes = array()
$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 string $errorMessage
Expand Down

0 comments on commit 7f90d91

Please sign in to comment.