annotate vendor/guzzlehttp/guzzle/src/RetryMiddleware.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 4c8ae668cc8c
children
rev   line source
Chris@0 1 <?php
Chris@0 2 namespace GuzzleHttp;
Chris@0 3
Chris@0 4 use GuzzleHttp\Promise\PromiseInterface;
Chris@0 5 use GuzzleHttp\Promise\RejectedPromise;
Chris@0 6 use GuzzleHttp\Psr7;
Chris@0 7 use Psr\Http\Message\RequestInterface;
Chris@0 8 use Psr\Http\Message\ResponseInterface;
Chris@0 9
Chris@0 10 /**
Chris@0 11 * Middleware that retries requests based on the boolean result of
Chris@0 12 * invoking the provided "decider" function.
Chris@0 13 */
Chris@0 14 class RetryMiddleware
Chris@0 15 {
Chris@0 16 /** @var callable */
Chris@0 17 private $nextHandler;
Chris@0 18
Chris@0 19 /** @var callable */
Chris@0 20 private $decider;
Chris@0 21
Chris@0 22 /**
Chris@0 23 * @param callable $decider Function that accepts the number of retries,
Chris@0 24 * a request, [response], and [exception] and
Chris@0 25 * returns true if the request is to be
Chris@0 26 * retried.
Chris@0 27 * @param callable $nextHandler Next handler to invoke.
Chris@0 28 * @param callable $delay Function that accepts the number of retries
Chris@0 29 * and [response] and returns the number of
Chris@0 30 * milliseconds to delay.
Chris@0 31 */
Chris@0 32 public function __construct(
Chris@0 33 callable $decider,
Chris@0 34 callable $nextHandler,
Chris@0 35 callable $delay = null
Chris@0 36 ) {
Chris@0 37 $this->decider = $decider;
Chris@0 38 $this->nextHandler = $nextHandler;
Chris@0 39 $this->delay = $delay ?: __CLASS__ . '::exponentialDelay';
Chris@0 40 }
Chris@0 41
Chris@0 42 /**
Chris@0 43 * Default exponential backoff delay function.
Chris@0 44 *
Chris@0 45 * @param $retries
Chris@0 46 *
Chris@0 47 * @return int
Chris@0 48 */
Chris@0 49 public static function exponentialDelay($retries)
Chris@0 50 {
Chris@0 51 return (int) pow(2, $retries - 1);
Chris@0 52 }
Chris@0 53
Chris@0 54 /**
Chris@0 55 * @param RequestInterface $request
Chris@0 56 * @param array $options
Chris@0 57 *
Chris@0 58 * @return PromiseInterface
Chris@0 59 */
Chris@0 60 public function __invoke(RequestInterface $request, array $options)
Chris@0 61 {
Chris@0 62 if (!isset($options['retries'])) {
Chris@0 63 $options['retries'] = 0;
Chris@0 64 }
Chris@0 65
Chris@0 66 $fn = $this->nextHandler;
Chris@0 67 return $fn($request, $options)
Chris@0 68 ->then(
Chris@0 69 $this->onFulfilled($request, $options),
Chris@0 70 $this->onRejected($request, $options)
Chris@0 71 );
Chris@0 72 }
Chris@0 73
Chris@0 74 private function onFulfilled(RequestInterface $req, array $options)
Chris@0 75 {
Chris@0 76 return function ($value) use ($req, $options) {
Chris@0 77 if (!call_user_func(
Chris@0 78 $this->decider,
Chris@0 79 $options['retries'],
Chris@0 80 $req,
Chris@0 81 $value,
Chris@0 82 null
Chris@0 83 )) {
Chris@0 84 return $value;
Chris@0 85 }
Chris@0 86 return $this->doRetry($req, $options, $value);
Chris@0 87 };
Chris@0 88 }
Chris@0 89
Chris@0 90 private function onRejected(RequestInterface $req, array $options)
Chris@0 91 {
Chris@0 92 return function ($reason) use ($req, $options) {
Chris@0 93 if (!call_user_func(
Chris@0 94 $this->decider,
Chris@0 95 $options['retries'],
Chris@0 96 $req,
Chris@0 97 null,
Chris@0 98 $reason
Chris@0 99 )) {
Chris@0 100 return \GuzzleHttp\Promise\rejection_for($reason);
Chris@0 101 }
Chris@0 102 return $this->doRetry($req, $options);
Chris@0 103 };
Chris@0 104 }
Chris@0 105
Chris@0 106 private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null)
Chris@0 107 {
Chris@0 108 $options['delay'] = call_user_func($this->delay, ++$options['retries'], $response);
Chris@0 109
Chris@0 110 return $this($request, $options);
Chris@0 111 }
Chris@0 112 }