Skip to content

Commit 4ec89be

Browse files
committed
Allow setRetry() methods to use callables
1 parent 0f1e16a commit 4ec89be

File tree

5 files changed

+219
-27
lines changed

5 files changed

+219
-27
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ More examples are available under [/examples](https://github.com/php-curl-class/
194194
Curl::__construct($base_url = null)
195195
Curl::__destruct()
196196
Curl::__get($name)
197+
Curl::attemptRetry()
197198
Curl::beforeSend($callback)
198199
Curl::buildPostData($data)
199200
Curl::call()
@@ -203,6 +204,7 @@ Curl::delete($url, $query_parameters = array(), $data = array())
203204
Curl::download($url, $mixed_filename)
204205
Curl::error($callback)
205206
Curl::exec($ch = null)
207+
Curl::execDone()
206208
Curl::get($url, $data = array())
207209
Curl::getCookie($key)
208210
Curl::getInfo($opt = null)
@@ -238,7 +240,7 @@ Curl::setOpts($options)
238240
Curl::setPort($port)
239241
Curl::setReferer($referer)
240242
Curl::setReferrer($referrer)
241-
Curl::setRetry($maximum_number_of_retries = 0)
243+
Curl::setRetry($mixed)
242244
Curl::setTimeout($seconds)
243245
Curl::setUrl($url, $mixed_data = '')
244246
Curl::setUserAgent($user_agent)
@@ -281,7 +283,7 @@ MultiCurl::setOpts($options)
281283
MultiCurl::setPort($port)
282284
MultiCurl::setReferer($referer)
283285
MultiCurl::setReferrer($referrer)
284-
MultiCurl::setRetry($maximum_number_of_retries = 0)
286+
MultiCurl::setRetry($mixed)
285287
MultiCurl::setTimeout($seconds)
286288
MultiCurl::setUrl($url)
287289
MultiCurl::setUserAgent($user_agent)

src/Curl/Curl.php

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class Curl
4545
public $retries = 0;
4646
public $isChildOfMultiCurl = false;
4747
public $remainingRetries = 0;
48-
private $maximumNumberOfRetries = 0;
48+
public $retryDecider = null;
4949

5050
private $cookies = array();
5151
private $headers = array();
@@ -390,18 +390,22 @@ public function exec($ch = null)
390390
}
391391
$this->errorMessage = $this->curlError ? $this->curlErrorMessage : $this->httpErrorMessage;
392392

393-
if ($this->error && $this->remainingRetries >= 1) {
394-
$this->retries += 1;
395-
396-
// Allow multicurl to update $remainingRetries and retry.
397-
if ($this->isChildOfMultiCurl) {
398-
return;
399-
}
393+
// Allow multicurl to attempt retry as needed.
394+
if ($this->isChildOfMultiCurl) {
395+
return;
396+
}
400397

401-
$this->remainingRetries -= 1;
398+
if ($this->attemptRetry()) {
402399
return $this->exec($ch);
403400
}
404401

402+
$this->execDone();
403+
404+
return $this->response;
405+
}
406+
407+
public function execDone()
408+
{
405409
if ($this->error) {
406410
$this->call($this->errorFunction);
407411
} else {
@@ -414,8 +418,6 @@ public function exec($ch = null)
414418
if (!($this->fileHandle === null)) {
415419
$this->downloadComplete($this->fileHandle);
416420
}
417-
418-
return $this->response;
419421
}
420422

421423
/**
@@ -1033,15 +1035,20 @@ public function setReferrer($referrer)
10331035
/**
10341036
* Set Retry
10351037
*
1036-
* Number of retries to attempt. Maximum number of attempts is $maximum_number_of_retries + 1.
1038+
* Number of retries to attempt or decider callable. Maximum number of
1039+
* attempts is $maximum_number_of_retries + 1.
10371040
*
10381041
* @access public
1039-
* @param $maximum_number_of_retries
1042+
* @param $mixed
10401043
*/
1041-
public function setRetry($maximum_number_of_retries = 0)
1044+
public function setRetry($mixed)
10421045
{
1043-
$this->maximumNumberOfRetries = $maximum_number_of_retries;
1044-
$this->remainingRetries = $this->maximumNumberOfRetries;
1046+
if (is_callable($mixed)) {
1047+
$this->retryDecider = $mixed;
1048+
} elseif (is_int($mixed)) {
1049+
$maximum_number_of_retries = $mixed;
1050+
$this->remainingRetries = $maximum_number_of_retries;
1051+
}
10451052
}
10461053

10471054
/**
@@ -1080,6 +1087,31 @@ public function setUserAgent($user_agent)
10801087
$this->setOpt(CURLOPT_USERAGENT, $user_agent);
10811088
}
10821089

1090+
/**
1091+
* Attempt Retry
1092+
*
1093+
* @access public
1094+
*/
1095+
public function attemptRetry()
1096+
{
1097+
$attempt_retry = false;
1098+
if ($this->error) {
1099+
if ($this->retryDecider === null) {
1100+
$attempt_retry = $this->remainingRetries >= 1;
1101+
} else {
1102+
$func = $this->retryDecider;
1103+
$attempt_retry = $func($this);
1104+
}
1105+
if ($attempt_retry) {
1106+
$this->retries += 1;
1107+
if ($this->remainingRetries) {
1108+
$this->remainingRetries -= 1;
1109+
}
1110+
}
1111+
}
1112+
return $attempt_retry;
1113+
}
1114+
10831115
/**
10841116
* Success
10851117
*

src/Curl/MultiCurl.php

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class MultiCurl
1818
private $errorFunction = null;
1919
private $completeFunction = null;
2020

21-
private $maximumNumberOfRetries = 0;
21+
private $retry = null;
2222

2323
private $cookies = array();
2424
private $headers = array();
@@ -592,14 +592,15 @@ public function setReferrer($referrer)
592592
/**
593593
* Set Retry
594594
*
595-
* Number of retries to attempt. Maximum number of attempts is $maximum_number_of_retries + 1.
595+
* Number of retries to attempt or decider callable. Maximum number of
596+
* attempts is $maximum_number_of_retries + 1.
596597
*
597598
* @access public
598-
* @param $maximum_number_of_retries
599+
* @param $mixed
599600
*/
600-
public function setRetry($maximum_number_of_retries = 0)
601+
public function setRetry($mixed)
601602
{
602-
$this->maximumNumberOfRetries = $maximum_number_of_retries;
603+
$this->retry = $mixed;
603604
}
604605

605606
/**
@@ -676,9 +677,7 @@ public function start()
676677
$ch->curlErrorCode = $info_array['result'];
677678
$ch->exec($ch->curl);
678679

679-
if ($ch->error && $ch->remainingRetries >= 1) {
680-
$ch->remainingRetries -= 1;
681-
680+
if ($ch->attemptRetry()) {
682681
// Remove completed handle before adding again in order to retry request.
683682
curl_multi_remove_handle($this->multiCurl, $ch->curl);
684683

@@ -689,6 +688,8 @@ public function start()
689688
);
690689
}
691690
} else {
691+
$ch->execDone();
692+
692693
// Remove completed instance from active curls.
693694
unset($this->activeCurls[$key]);
694695

@@ -821,7 +822,7 @@ private function initHandle($curl)
821822

822823
$curl->setOpts($this->options);
823824
$curl->setHeaders($this->headers);
824-
$curl->setRetry($this->maximumNumberOfRetries);
825+
$curl->setRetry($this->retry);
825826

826827
foreach ($this->cookies as $key => $value) {
827828
$curl->setCookie($key, $value);

tests/PHPCurlClass/PHPCurlClassTest.php

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3321,4 +3321,81 @@ public function testRetry()
33213321
$this->assertEquals($expect_retries, $test->curl->retries);
33223322
}
33233323
}
3324+
3325+
public function testRetryCallable()
3326+
{
3327+
$tests = array(
3328+
array(
3329+
'maximum_number_of_retries' => null,
3330+
'failures' => 0,
3331+
'expect_success' => true,
3332+
'expect_attempts' => 1,
3333+
'expect_retries' => 0,
3334+
),
3335+
array(
3336+
'maximum_number_of_retries' => 0,
3337+
'failures' => 0,
3338+
'expect_success' => true,
3339+
'expect_attempts' => 1,
3340+
'expect_retries' => 0,
3341+
),
3342+
array(
3343+
'maximum_number_of_retries' => 0,
3344+
'failures' => 1,
3345+
'expect_success' => false,
3346+
'expect_attempts' => 1,
3347+
'expect_retries' => 0,
3348+
),
3349+
array(
3350+
'maximum_number_of_retries' => 1,
3351+
'failures' => 1,
3352+
'expect_success' => true,
3353+
'expect_attempts' => 2,
3354+
'expect_retries' => 1,
3355+
),
3356+
array(
3357+
'maximum_number_of_retries' => 1,
3358+
'failures' => 2,
3359+
'expect_success' => false,
3360+
'expect_attempts' => 2,
3361+
'expect_retries' => 1,
3362+
),
3363+
array(
3364+
'maximum_number_of_retries' => 2,
3365+
'failures' => 2,
3366+
'expect_success' => true,
3367+
'expect_attempts' => 3,
3368+
'expect_retries' => 2,
3369+
),
3370+
array(
3371+
'maximum_number_of_retries' => 3,
3372+
'failures' => 3,
3373+
'expect_success' => true,
3374+
'expect_attempts' => 4,
3375+
'expect_retries' => 3,
3376+
),
3377+
);
3378+
foreach ($tests as $test) {
3379+
$maximum_number_of_retries = $test['maximum_number_of_retries'];
3380+
$failures = $test['failures'];
3381+
$expect_success = $test['expect_success'];
3382+
$expect_attempts = $test['expect_attempts'];
3383+
$expect_retries = $test['expect_retries'];
3384+
3385+
$test = new Test();
3386+
$test->curl->setOpt(CURLOPT_COOKIEJAR, '/dev/null');
3387+
3388+
if (!($maximum_number_of_retries === null)) {
3389+
$test->curl->setRetry(function ($instance) use ($maximum_number_of_retries) {
3390+
$return = $instance->retries < $maximum_number_of_retries;
3391+
return $return;
3392+
});
3393+
}
3394+
3395+
$test->server('retry', 'GET', array('failures' => $failures));
3396+
$this->assertEquals($expect_success, !$test->curl->error);
3397+
$this->assertEquals($expect_attempts, $test->curl->attempts);
3398+
$this->assertEquals($expect_retries, $test->curl->retries);
3399+
}
3400+
}
33243401
}

tests/PHPCurlClass/PHPMultiCurlClassTest.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2667,4 +2667,84 @@ public function testRetryMulti()
26672667
$this->assertEquals($expect_retries, $instance->retries);
26682668
}
26692669
}
2670+
2671+
public function testRetryCallableMulti()
2672+
{
2673+
$tests = array(
2674+
array(
2675+
'maximum_number_of_retries' => null,
2676+
'failures' => 0,
2677+
'expect_success' => true,
2678+
'expect_attempts' => 1,
2679+
'expect_retries' => 0,
2680+
),
2681+
array(
2682+
'maximum_number_of_retries' => 0,
2683+
'failures' => 0,
2684+
'expect_success' => true,
2685+
'expect_attempts' => 1,
2686+
'expect_retries' => 0,
2687+
),
2688+
array(
2689+
'maximum_number_of_retries' => 0,
2690+
'failures' => 1,
2691+
'expect_success' => false,
2692+
'expect_attempts' => 1,
2693+
'expect_retries' => 0,
2694+
),
2695+
array(
2696+
'maximum_number_of_retries' => 1,
2697+
'failures' => 1,
2698+
'expect_success' => true,
2699+
'expect_attempts' => 2,
2700+
'expect_retries' => 1,
2701+
),
2702+
array(
2703+
'maximum_number_of_retries' => 1,
2704+
'failures' => 2,
2705+
'expect_success' => false,
2706+
'expect_attempts' => 2,
2707+
'expect_retries' => 1,
2708+
),
2709+
array(
2710+
'maximum_number_of_retries' => 2,
2711+
'failures' => 2,
2712+
'expect_success' => true,
2713+
'expect_attempts' => 3,
2714+
'expect_retries' => 2,
2715+
),
2716+
array(
2717+
'maximum_number_of_retries' => 3,
2718+
'failures' => 3,
2719+
'expect_success' => true,
2720+
'expect_attempts' => 4,
2721+
'expect_retries' => 3,
2722+
),
2723+
);
2724+
foreach ($tests as $test) {
2725+
$maximum_number_of_retries = $test['maximum_number_of_retries'];
2726+
$failures = $test['failures'];
2727+
$expect_success = $test['expect_success'];
2728+
$expect_attempts = $test['expect_attempts'];
2729+
$expect_retries = $test['expect_retries'];
2730+
2731+
$multi_curl = new MultiCurl();
2732+
$multi_curl->setOpt(CURLOPT_COOKIEJAR, '/dev/null');
2733+
$multi_curl->setHeader('X-DEBUG-TEST', 'retry');
2734+
2735+
if (!($maximum_number_of_retries === null)) {
2736+
$multi_curl->setRetry(function ($instance) use ($maximum_number_of_retries) {
2737+
$return = $instance->retries < $maximum_number_of_retries;
2738+
return $return;
2739+
});
2740+
}
2741+
2742+
$instance = $multi_curl->addGet(Test::TEST_URL, array('failures' => $failures));
2743+
$multi_curl->start();
2744+
2745+
$this->assertEquals($expect_success, !$instance->error);
2746+
$this->assertEquals($expect_attempts, $instance->attempts);
2747+
$this->assertEquals($expect_retries, $instance->retries);
2748+
}
2749+
}
26702750
}

0 commit comments

Comments
 (0)