diff --git a/CHANGELOG.md b/CHANGELOG.md index ddc4122..c8b2a02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Change Log +## 1.9.0 - [unreleased] + +### Changed + +- [RetryPlugin] Renamed the configuration options for the exception retry callback from `decider` to `exception_decider` + and `delay` to `exception_delay`. The old names still work but are deprecated. + ## 1.8.2 - 2018-12-14 ### Changed diff --git a/spec/Plugin/RetryPluginSpec.php b/spec/Plugin/RetryPluginSpec.php index 37800ae..4a985f3 100644 --- a/spec/Plugin/RetryPluginSpec.php +++ b/spec/Plugin/RetryPluginSpec.php @@ -80,6 +80,30 @@ function it_returns_response_on_second_try(RequestInterface $request, ResponseIn $promise->wait()->shouldReturn($response); } + function it_respects_custom_exception_decider(RequestInterface $request, ResponseInterface $response) + { + $this->beConstructedWith([ + 'exception_decider' => function (RequestInterface $request, Exception $e) { + return false; + } + ]); + $exception = new Exception\NetworkException('Exception', $request->getWrappedObject()); + + $called = false; + $next = function (RequestInterface $receivedRequest) use($exception, &$called) { + if ($called) { + throw new \RuntimeException('Did not expect to be called multiple times'); + } + $called = true; + + return new HttpRejectedPromise($exception); + }; + + $promise = $this->handleRequest($request, $next, function () {}); + $promise->shouldReturnAnInstanceOf('Http\Client\Promise\HttpRejectedPromise'); + $promise->shouldThrow($exception)->duringWait(); + } + function it_does_not_keep_history_of_old_failure(RequestInterface $request, ResponseInterface $response) { $exception = new Exception\NetworkException('Exception 1', $request->getWrappedObject()); diff --git a/src/Plugin/RetryPlugin.php b/src/Plugin/RetryPlugin.php index 8446246..3d09265 100644 --- a/src/Plugin/RetryPlugin.php +++ b/src/Plugin/RetryPlugin.php @@ -27,12 +27,12 @@ final class RetryPlugin implements Plugin /** * @var callable */ - private $delay; + private $exceptionDelay; /** * @var callable */ - private $decider; + private $exceptionDecider; /** * Store the retry counter for each request. @@ -45,28 +45,45 @@ final class RetryPlugin implements Plugin * @param array $config { * * @var int $retries Number of retries to attempt if an exception occurs before letting the exception bubble up. - * @var callable $decider A callback that gets a request and an exception to decide after a failure whether the request should be retried. - * @var callable $delay A callback that gets a request, an exception and the number of retries and returns how many microseconds we should wait before trying again. + * @var callable $exception_decider A callback that gets a request and an exception to decide after a failure whether the request should be retried. + * @var callable $exception_delay A callback that gets a request, an exception and the number of retries and returns how many microseconds we should wait before trying again. * } */ public function __construct(array $config = []) { + if (array_key_exists('decider', $config)) { + if (array_key_exists('exception_decider', $config)) { + throw new \InvalidArgumentException('Do not set both the old "decider" and new "exception_decider" options'); + } + trigger_error('The "decider" option has been deprecated in favour of "exception_decider"', E_USER_DEPRECATED); + $config['exception_decider'] = $config['decider']; + unset($config['decider']); + } + if (array_key_exists('delay', $config)) { + if (array_key_exists('exception_delay', $config)) { + throw new \InvalidArgumentException('Do not set both the old "delay" and new "exception_delay" options'); + } + trigger_error('The "delay" option has been deprecated in favour of "exception_delay"', E_USER_DEPRECATED); + $config['exception_delay'] = $config['delay']; + unset($config['delay']); + } + $resolver = new OptionsResolver(); $resolver->setDefaults([ 'retries' => 1, - 'decider' => function (RequestInterface $request, Exception $e) { + 'exception_decider' => function (RequestInterface $request, Exception $e) { return true; }, - 'delay' => __CLASS__.'::defaultDelay', + 'exception_delay' => __CLASS__.'::defaultDelay', ]); $resolver->setAllowedTypes('retries', 'int'); - $resolver->setAllowedTypes('decider', 'callable'); - $resolver->setAllowedTypes('delay', 'callable'); + $resolver->setAllowedTypes('exception_decider', 'callable'); + $resolver->setAllowedTypes('exception_delay', 'callable'); $options = $resolver->resolve($config); $this->retry = $options['retries']; - $this->decider = $options['decider']; - $this->delay = $options['delay']; + $this->exceptionDecider = $options['exception_decider']; + $this->exceptionDelay = $options['exception_delay']; } /** @@ -93,11 +110,11 @@ public function handleRequest(RequestInterface $request, callable $next, callabl throw $exception; } - if (!call_user_func($this->decider, $request, $exception)) { + if (!call_user_func($this->exceptionDecider, $request, $exception)) { throw $exception; } - $time = call_user_func($this->delay, $request, $exception, $this->retryStorage[$chainIdentifier]); + $time = call_user_func($this->exceptionDelay, $request, $exception, $this->retryStorage[$chainIdentifier]); usleep($time); // Retry in synchrone