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