PluginProbe
Depicter — Popup & Slider Builder / 1.9.6
Depicter — Popup & Slider Builder v1.9.6
4.8.1 trunk 1.0.0 1.1.0 1.1.2 1.1.4 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.5 1.3.8 1.5.0 1.5.1 1.5.2 1.5.5 1.6.0 1.6.1 1.6.2 1.7.0 All 76 releases
depicter / modules / GuzzleHttp / RetryMiddleware.php

RetryMiddleware.php in Depicter — Popup & Slider Builder 1.9.6, at modules/GuzzleHttp/RetryMiddleware.php

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