@@ -18,6 +18,8 @@ class MultiCurl
1818 private $ errorFunction = null ;
1919 private $ completeFunction = null ;
2020
21+ private $ maximumNumberOfRetries = 0 ;
22+
2123 private $ cookies = array ();
2224 private $ headers = array ();
2325 private $ options = array ();
@@ -587,6 +589,19 @@ public function setReferrer($referrer)
587589 $ this ->setOpt (CURLOPT_REFERER , $ referrer );
588590 }
589591
592+ /**
593+ * Set Retry
594+ *
595+ * Number of retries to attempt. Maximum number of attempts is $maximum_number_of_retries + 1.
596+ *
597+ * @access public
598+ * @param $maximum_number_of_retries
599+ */
600+ public function setRetry ($ maximum_number_of_retries = 0 )
601+ {
602+ $ this ->maximumNumberOfRetries = $ maximum_number_of_retries ;
603+ }
604+
590605 /**
591606 * Set Timeout
592607 *
@@ -661,17 +676,31 @@ public function start()
661676 $ ch ->curlErrorCode = $ info_array ['result ' ];
662677 $ ch ->exec ($ ch ->curl );
663678
664- // Remove completed instance from active curls.
665- unset($ this ->activeCurls [$ key ]);
666-
667- // Start a new request before removing the handle of the completed one.
668- if (count ($ this ->curls ) >= 1 ) {
669- $ this ->initHandle (array_shift ($ this ->curls ));
679+ if ($ ch ->error && $ ch ->remainingRetries >= 1 ) {
680+ $ ch ->remainingRetries -= 1 ;
681+
682+ // Remove completed handle before adding again in order to retry request.
683+ curl_multi_remove_handle ($ this ->multiCurl , $ ch ->curl );
684+
685+ $ curlm_error_code = curl_multi_add_handle ($ this ->multiCurl , $ ch ->curl );
686+ if (!($ curlm_error_code === CURLM_OK )) {
687+ throw new \ErrorException (
688+ 'cURL multi add handle error: ' . curl_multi_strerror ($ curlm_error_code )
689+ );
690+ }
691+ } else {
692+ // Remove completed instance from active curls.
693+ unset($ this ->activeCurls [$ key ]);
694+
695+ // Start a new request before removing the handle of the completed one.
696+ if (count ($ this ->curls ) >= 1 ) {
697+ $ this ->initHandle (array_shift ($ this ->curls ));
698+ }
699+ curl_multi_remove_handle ($ this ->multiCurl , $ ch ->curl );
700+
701+ // Clean up completed instance.
702+ $ ch ->close ();
670703 }
671- curl_multi_remove_handle ($ this ->multiCurl , $ ch ->curl );
672-
673- // Clean up completed instance.
674- $ ch ->close ();
675704
676705 break ;
677706 }
@@ -763,6 +792,7 @@ private function queueHandle($curl)
763792 {
764793 // Use sequential ids to allow for ordered post processing.
765794 $ curl ->id = $ this ->nextCurlId ++;
795+ $ curl ->isChildOfMultiCurl = true ;
766796 $ this ->curls [$ curl ->id ] = $ curl ;
767797 }
768798
@@ -791,6 +821,7 @@ private function initHandle($curl)
791821
792822 $ curl ->setOpts ($ this ->options );
793823 $ curl ->setHeaders ($ this ->headers );
824+ $ curl ->setRetry ($ this ->maximumNumberOfRetries );
794825
795826 foreach ($ this ->cookies as $ key => $ value ) {
796827 $ curl ->setCookie ($ key , $ value );
0 commit comments