Implement MultiCurl::setRetry()

This commit is contained in:
Zach Borboa
2017-08-31 01:26:42 -07:00
parent 3c3741f891
commit 0f1e16a6fa
5 changed files with 134 additions and 11 deletions
+1
View File
@@ -281,6 +281,7 @@ MultiCurl::setOpts($options)
MultiCurl::setPort($port)
MultiCurl::setReferer($referer)
MultiCurl::setReferrer($referrer)
MultiCurl::setRetry($maximum_number_of_retries = 0)
MultiCurl::setTimeout($seconds)
MultiCurl::setUrl($url)
MultiCurl::setUserAgent($user_agent)
+9 -2
View File
@@ -43,8 +43,9 @@ class Curl
public $attempts = 0;
public $retries = 0;
public $isChildOfMultiCurl = false;
public $remainingRetries = 0;
private $maximumNumberOfRetries = 0;
private $remainingRetries = 0;
private $cookies = array();
private $headers = array();
@@ -390,8 +391,14 @@ class Curl
$this->errorMessage = $this->curlError ? $this->curlErrorMessage : $this->httpErrorMessage;
if ($this->error && $this->remainingRetries >= 1) {
$this->remainingRetries -= 1;
$this->retries += 1;
// Allow multicurl to update $remainingRetries and retry.
if ($this->isChildOfMultiCurl) {
return;
}
$this->remainingRetries -= 1;
return $this->exec($ch);
}
+40 -9
View File
@@ -18,6 +18,8 @@ class MultiCurl
private $errorFunction = null;
private $completeFunction = null;
private $maximumNumberOfRetries = 0;
private $cookies = array();
private $headers = array();
private $options = array();
@@ -587,6 +589,19 @@ class MultiCurl
$this->setOpt(CURLOPT_REFERER, $referrer);
}
/**
* Set Retry
*
* Number of retries to attempt. Maximum number of attempts is $maximum_number_of_retries + 1.
*
* @access public
* @param $maximum_number_of_retries
*/
public function setRetry($maximum_number_of_retries = 0)
{
$this->maximumNumberOfRetries = $maximum_number_of_retries;
}
/**
* Set Timeout
*
@@ -661,17 +676,31 @@ class MultiCurl
$ch->curlErrorCode = $info_array['result'];
$ch->exec($ch->curl);
// Remove completed instance from active curls.
unset($this->activeCurls[$key]);
if ($ch->error && $ch->remainingRetries >= 1) {
$ch->remainingRetries -= 1;
// Start a new request before removing the handle of the completed one.
if (count($this->curls) >= 1) {
$this->initHandle(array_shift($this->curls));
// Remove completed handle before adding again in order to retry request.
curl_multi_remove_handle($this->multiCurl, $ch->curl);
$curlm_error_code = curl_multi_add_handle($this->multiCurl, $ch->curl);
if (!($curlm_error_code === CURLM_OK)) {
throw new \ErrorException(
'cURL multi add handle error: ' . curl_multi_strerror($curlm_error_code)
);
}
} else {
// Remove completed instance from active curls.
unset($this->activeCurls[$key]);
// Start a new request before removing the handle of the completed one.
if (count($this->curls) >= 1) {
$this->initHandle(array_shift($this->curls));
}
curl_multi_remove_handle($this->multiCurl, $ch->curl);
// Clean up completed instance.
$ch->close();
}
curl_multi_remove_handle($this->multiCurl, $ch->curl);
// Clean up completed instance.
$ch->close();
break;
}
@@ -763,6 +792,7 @@ class MultiCurl
{
// Use sequential ids to allow for ordered post processing.
$curl->id = $this->nextCurlId++;
$curl->isChildOfMultiCurl = true;
$this->curls[$curl->id] = $curl;
}
@@ -791,6 +821,7 @@ class MultiCurl
$curl->setOpts($this->options);
$curl->setHeaders($this->headers);
$curl->setRetry($this->maximumNumberOfRetries);
foreach ($this->cookies as $key => $value) {
$curl->setCookie($key, $value);
+7
View File
@@ -3293,6 +3293,13 @@ class CurlTest extends \PHPUnit\Framework\TestCase
'expect_attempts' => 3,
'expect_retries' => 2,
),
array(
'maximum_number_of_retries' => 3,
'failures' => 3,
'expect_success' => true,
'expect_attempts' => 4,
'expect_retries' => 3,
),
);
foreach ($tests as $test) {
$maximum_number_of_retries = $test['maximum_number_of_retries'];
@@ -2590,4 +2590,81 @@ class MultiCurlTest extends \PHPUnit\Framework\TestCase
$multi_curl->start();
}
public function testRetryMulti()
{
$tests = array(
array(
'maximum_number_of_retries' => null,
'failures' => 0,
'expect_success' => true,
'expect_attempts' => 1,
'expect_retries' => 0,
),
array(
'maximum_number_of_retries' => 0,
'failures' => 0,
'expect_success' => true,
'expect_attempts' => 1,
'expect_retries' => 0,
),
array(
'maximum_number_of_retries' => 0,
'failures' => 1,
'expect_success' => false,
'expect_attempts' => 1,
'expect_retries' => 0,
),
array(
'maximum_number_of_retries' => 1,
'failures' => 1,
'expect_success' => true,
'expect_attempts' => 2,
'expect_retries' => 1,
),
array(
'maximum_number_of_retries' => 1,
'failures' => 2,
'expect_success' => false,
'expect_attempts' => 2,
'expect_retries' => 1,
),
array(
'maximum_number_of_retries' => 2,
'failures' => 2,
'expect_success' => true,
'expect_attempts' => 3,
'expect_retries' => 2,
),
array(
'maximum_number_of_retries' => 3,
'failures' => 3,
'expect_success' => true,
'expect_attempts' => 4,
'expect_retries' => 3,
),
);
foreach ($tests as $test) {
$maximum_number_of_retries = $test['maximum_number_of_retries'];
$failures = $test['failures'];
$expect_success = $test['expect_success'];
$expect_attempts = $test['expect_attempts'];
$expect_retries = $test['expect_retries'];
$multi_curl = new MultiCurl();
$multi_curl->setOpt(CURLOPT_COOKIEJAR, '/dev/null');
$multi_curl->setHeader('X-DEBUG-TEST', 'retry');
if (!($maximum_number_of_retries === null)) {
$multi_curl->setRetry($maximum_number_of_retries);
}
$instance = $multi_curl->addGet(Test::TEST_URL, array('failures' => $failures));
$multi_curl->start();
$this->assertEquals($expect_success, !$instance->error);
$this->assertEquals($expect_attempts, $instance->attempts);
$this->assertEquals($expect_retries, $instance->retries);
}
}
}