PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 1.2.20
Booking for Appointments and Events Calendar – Amelia v1.2.20
2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / vendor / php-http / client-common / src / Plugin / RetryPlugin.php
ameliabooking / vendor / php-http / client-common / src / Plugin Last commit date
AddHostPlugin.php 3 years ago AddPathPlugin.php 3 years ago AuthenticationPlugin.php 3 years ago BaseUriPlugin.php 3 years ago ContentLengthPlugin.php 3 years ago ContentTypePlugin.php 3 years ago CookiePlugin.php 3 years ago DecoderPlugin.php 3 years ago ErrorPlugin.php 3 years ago HeaderAppendPlugin.php 3 years ago HeaderDefaultsPlugin.php 3 years ago HeaderRemovePlugin.php 3 years ago HeaderSetPlugin.php 3 years ago HistoryPlugin.php 3 years ago Journal.php 3 years ago QueryDefaultsPlugin.php 3 years ago RedirectPlugin.php 3 years ago RequestMatcherPlugin.php 3 years ago RetryPlugin.php 3 years ago VersionBridgePlugin.php 3 years ago
RetryPlugin.php
140 lines
1 <?php
2
3 namespace AmeliaHttp\Client\Common\Plugin;
4
5 use AmeliaHttp\Client\Common\Plugin;
6 use AmeliaHttp\Client\Exception;
7 use AmeliaPsr\Http\Message\RequestInterface;
8 use AmeliaPsr\Http\Message\ResponseInterface;
9 use Symfony\Component\OptionsResolver\OptionsResolver;
10
11 /**
12 * Retry the request if an exception is thrown.
13 *
14 * By default will retry only one time.
15 *
16 * @author Joel Wurtz <joel.wurtz@gmail.com>
17 */
18 final class RetryPlugin implements Plugin
19 {
20 /**
21 * Number of retry before sending an exception.
22 *
23 * @var int
24 */
25 private $retry;
26
27 /**
28 * @var callable
29 */
30 private $exceptionDelay;
31
32 /**
33 * @var callable
34 */
35 private $exceptionDecider;
36
37 /**
38 * Store the retry counter for each request.
39 *
40 * @var array
41 */
42 private $retryStorage = [];
43
44 /**
45 * @param array $config {
46 *
47 * @var int $retries Number of retries to attempt if an exception occurs before letting the exception bubble up.
48 * @var callable $exception_decider A callback that gets a request and an exception to decide after a failure whether the request should be retried.
49 * @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.
50 * }
51 */
52 public function __construct(array $config = [])
53 {
54 if (array_key_exists('decider', $config)) {
55 if (array_key_exists('exception_decider', $config)) {
56 throw new \InvalidArgumentException('Do not set both the old "decider" and new "exception_decider" options');
57 }
58 trigger_error('The "decider" option has been deprecated in favour of "exception_decider"', E_USER_DEPRECATED);
59 $config['exception_decider'] = $config['decider'];
60 unset($config['decider']);
61 }
62 if (array_key_exists('delay', $config)) {
63 if (array_key_exists('exception_delay', $config)) {
64 throw new \InvalidArgumentException('Do not set both the old "delay" and new "exception_delay" options');
65 }
66 trigger_error('The "delay" option has been deprecated in favour of "exception_delay"', E_USER_DEPRECATED);
67 $config['exception_delay'] = $config['delay'];
68 unset($config['delay']);
69 }
70
71 $resolver = new OptionsResolver();
72 $resolver->setDefaults([
73 'retries' => 1,
74 'exception_decider' => function (RequestInterface $request, Exception $e) {
75 return true;
76 },
77 'exception_delay' => __CLASS__.'::defaultDelay',
78 ]);
79 $resolver->setAllowedTypes('retries', 'int');
80 $resolver->setAllowedTypes('exception_decider', 'callable');
81 $resolver->setAllowedTypes('exception_delay', 'callable');
82 $options = $resolver->resolve($config);
83
84 $this->retry = $options['retries'];
85 $this->exceptionDecider = $options['exception_decider'];
86 $this->exceptionDelay = $options['exception_delay'];
87 }
88
89 /**
90 * {@inheritdoc}
91 */
92 public function handleRequest(RequestInterface $request, callable $next, callable $first)
93 {
94 $chainIdentifier = spl_object_hash((object) $first);
95
96 return $next($request)->then(function (ResponseInterface $response) use ($request, $chainIdentifier) {
97 if (array_key_exists($chainIdentifier, $this->retryStorage)) {
98 unset($this->retryStorage[$chainIdentifier]);
99 }
100
101 return $response;
102 }, function (Exception $exception) use ($request, $next, $first, $chainIdentifier) {
103 if (!array_key_exists($chainIdentifier, $this->retryStorage)) {
104 $this->retryStorage[$chainIdentifier] = 0;
105 }
106
107 if ($this->retryStorage[$chainIdentifier] >= $this->retry) {
108 unset($this->retryStorage[$chainIdentifier]);
109
110 throw $exception;
111 }
112
113 if (!call_user_func($this->exceptionDecider, $request, $exception)) {
114 throw $exception;
115 }
116
117 $time = call_user_func($this->exceptionDelay, $request, $exception, $this->retryStorage[$chainIdentifier]);
118 usleep($time);
119
120 // Retry in synchrone
121 ++$this->retryStorage[$chainIdentifier];
122 $promise = $this->handleRequest($request, $next, $first);
123
124 return $promise->wait();
125 });
126 }
127
128 /**
129 * @param RequestInterface $request
130 * @param Exception $e
131 * @param int $retries The number of retries we made before. First time this get called it will be 0.
132 *
133 * @return int
134 */
135 public static function defaultDelay(RequestInterface $request, Exception $e, $retries)
136 {
137 return pow(2, $retries) * 500000;
138 }
139 }
140