Allow setRetry() methods to use callables

This commit is contained in:
Zach Borboa
2017-09-02 02:23:40 -07:00
parent 0f1e16a6fa
commit 4ec89be9bc
5 changed files with 219 additions and 27 deletions
+4 -2
View File
@@ -194,6 +194,7 @@ More examples are available under [/examples](https://github.com/php-curl-class/
Curl::__construct($base_url = null)
Curl::__destruct()
Curl::__get($name)
Curl::attemptRetry()
Curl::beforeSend($callback)
Curl::buildPostData($data)
Curl::call()
@@ -203,6 +204,7 @@ Curl::delete($url, $query_parameters = array(), $data = array())
Curl::download($url, $mixed_filename)
Curl::error($callback)
Curl::exec($ch = null)
Curl::execDone()
Curl::get($url, $data = array())
Curl::getCookie($key)
Curl::getInfo($opt = null)
@@ -238,7 +240,7 @@ Curl::setOpts($options)
Curl::setPort($port)
Curl::setReferer($referer)
Curl::setReferrer($referrer)
Curl::setRetry($maximum_number_of_retries = 0)
Curl::setRetry($mixed)
Curl::setTimeout($seconds)
Curl::setUrl($url, $mixed_data = '')
Curl::setUserAgent($user_agent)
@@ -281,7 +283,7 @@ MultiCurl::setOpts($options)
MultiCurl::setPort($port)
MultiCurl::setReferer($referer)
MultiCurl::setReferrer($referrer)
MultiCurl::setRetry($maximum_number_of_retries = 0)
MultiCurl::setRetry($mixed)
MultiCurl::setTimeout($seconds)
MultiCurl::setUrl($url)
MultiCurl::setUserAgent($user_agent)
+48 -16
View File
@@ -45,7 +45,7 @@ class Curl
public $retries = 0;
public $isChildOfMultiCurl = false;
public $remainingRetries = 0;
private $maximumNumberOfRetries = 0;
public $retryDecider = null;
private $cookies = array();
private $headers = array();
@@ -390,18 +390,22 @@ class Curl
}
$this->errorMessage = $this->curlError ? $this->curlErrorMessage : $this->httpErrorMessage;
if ($this->error && $this->remainingRetries >= 1) {
$this->retries += 1;
// Allow multicurl to attempt retry as needed.
if ($this->isChildOfMultiCurl) {
return;
}
// Allow multicurl to update $remainingRetries and retry.
if ($this->isChildOfMultiCurl) {
return;
}
$this->remainingRetries -= 1;
if ($this->attemptRetry()) {
return $this->exec($ch);
}
$this->execDone();
return $this->response;
}
public function execDone()
{
if ($this->error) {
$this->call($this->errorFunction);
} else {
@@ -414,8 +418,6 @@ class Curl
if (!($this->fileHandle === null)) {
$this->downloadComplete($this->fileHandle);
}
return $this->response;
}
/**
@@ -1033,15 +1035,20 @@ class Curl
/**
* Set Retry
*
* Number of retries to attempt. Maximum number of attempts is $maximum_number_of_retries + 1.
* Number of retries to attempt or decider callable. Maximum number of
* attempts is $maximum_number_of_retries + 1.
*
* @access public
* @param $maximum_number_of_retries
* @param $mixed
*/
public function setRetry($maximum_number_of_retries = 0)
public function setRetry($mixed)
{
$this->maximumNumberOfRetries = $maximum_number_of_retries;
$this->remainingRetries = $this->maximumNumberOfRetries;
if (is_callable($mixed)) {
$this->retryDecider = $mixed;
} elseif (is_int($mixed)) {
$maximum_number_of_retries = $mixed;
$this->remainingRetries = $maximum_number_of_retries;
}
}
/**
@@ -1080,6 +1087,31 @@ class Curl
$this->setOpt(CURLOPT_USERAGENT, $user_agent);
}
/**
* Attempt Retry
*
* @access public
*/
public function attemptRetry()
{
$attempt_retry = false;
if ($this->error) {
if ($this->retryDecider === null) {
$attempt_retry = $this->remainingRetries >= 1;
} else {
$func = $this->retryDecider;
$attempt_retry = $func($this);
}
if ($attempt_retry) {
$this->retries += 1;
if ($this->remainingRetries) {
$this->remainingRetries -= 1;
}
}
}
return $attempt_retry;
}
/**
* Success
*
+10 -9
View File
@@ -18,7 +18,7 @@ class MultiCurl
private $errorFunction = null;
private $completeFunction = null;
private $maximumNumberOfRetries = 0;
private $retry = null;
private $cookies = array();
private $headers = array();
@@ -592,14 +592,15 @@ class MultiCurl
/**
* Set Retry
*
* Number of retries to attempt. Maximum number of attempts is $maximum_number_of_retries + 1.
* Number of retries to attempt or decider callable. Maximum number of
* attempts is $maximum_number_of_retries + 1.
*
* @access public
* @param $maximum_number_of_retries
* @param $mixed
*/
public function setRetry($maximum_number_of_retries = 0)
public function setRetry($mixed)
{
$this->maximumNumberOfRetries = $maximum_number_of_retries;
$this->retry = $mixed;
}
/**
@@ -676,9 +677,7 @@ class MultiCurl
$ch->curlErrorCode = $info_array['result'];
$ch->exec($ch->curl);
if ($ch->error && $ch->remainingRetries >= 1) {
$ch->remainingRetries -= 1;
if ($ch->attemptRetry()) {
// Remove completed handle before adding again in order to retry request.
curl_multi_remove_handle($this->multiCurl, $ch->curl);
@@ -689,6 +688,8 @@ class MultiCurl
);
}
} else {
$ch->execDone();
// Remove completed instance from active curls.
unset($this->activeCurls[$key]);
@@ -821,7 +822,7 @@ class MultiCurl
$curl->setOpts($this->options);
$curl->setHeaders($this->headers);
$curl->setRetry($this->maximumNumberOfRetries);
$curl->setRetry($this->retry);
foreach ($this->cookies as $key => $value) {
$curl->setCookie($key, $value);
+77
View File
@@ -3321,4 +3321,81 @@ class CurlTest extends \PHPUnit\Framework\TestCase
$this->assertEquals($expect_retries, $test->curl->retries);
}
}
public function testRetryCallable()
{
$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'];
$test = new Test();
$test->curl->setOpt(CURLOPT_COOKIEJAR, '/dev/null');
if (!($maximum_number_of_retries === null)) {
$test->curl->setRetry(function ($instance) use ($maximum_number_of_retries) {
$return = $instance->retries < $maximum_number_of_retries;
return $return;
});
}
$test->server('retry', 'GET', array('failures' => $failures));
$this->assertEquals($expect_success, !$test->curl->error);
$this->assertEquals($expect_attempts, $test->curl->attempts);
$this->assertEquals($expect_retries, $test->curl->retries);
}
}
}
@@ -2667,4 +2667,84 @@ class MultiCurlTest extends \PHPUnit\Framework\TestCase
$this->assertEquals($expect_retries, $instance->retries);
}
}
public function testRetryCallableMulti()
{
$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(function ($instance) use ($maximum_number_of_retries) {
$return = $instance->retries < $maximum_number_of_retries;
return $return;
});
}
$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);
}
}
}