Complex classes like GuzzleRetryMiddleware often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use GuzzleRetryMiddleware, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
45 | class GuzzleRetryMiddleware |
||
46 | { |
||
47 | // HTTP date format |
||
48 | public const DATE_FORMAT = 'D, d M Y H:i:s T'; |
||
49 | |||
50 | // Default retry header (off by default; configurable) |
||
51 | public const RETRY_HEADER = 'X-Retry-Counter'; |
||
52 | |||
53 | // Default retry-after header |
||
54 | public const RETRY_AFTER_HEADER = 'Retry-After'; |
||
55 | |||
56 | /** |
||
57 | * @var array<mixed> |
||
58 | */ |
||
59 | private $defaultOptions = [ |
||
60 | |||
61 | // Retry enabled. Toggle retry on or off per request |
||
62 | 'retry_enabled' => true, |
||
63 | |||
64 | // If server doesn't provide a Retry-After header, then set a default back-off delay |
||
65 | // NOTE: This can either be a float, or it can be a callable that returns a (accepts count and response|null) |
||
66 | 'default_retry_multiplier' => 1.5, |
||
67 | |||
68 | // Set a maximum number of attempts per request |
||
69 | 'max_retry_attempts' => 10, |
||
70 | |||
71 | // Maximum allowable timeout seconds |
||
72 | 'max_allowable_timeout_secs' => null, |
||
73 | |||
74 | // Set this to TRUE to retry only if the HTTP Retry-After header is specified |
||
75 | 'retry_only_if_retry_after_header' => false, |
||
76 | |||
77 | // Only retry when status is equal to these response codes |
||
78 | 'retry_on_status' => ['429', '503'], |
||
79 | |||
80 | // Callback to trigger before delay occurs (accepts count, delay, request, response, options) |
||
81 | 'on_retry_callback' => null, |
||
82 | |||
83 | // Retry on connect timeout? |
||
84 | 'retry_on_timeout' => false, |
||
85 | |||
86 | // Add the number of retries to an X-Header |
||
87 | 'expose_retry_header' => false, |
||
88 | |||
89 | // The header key |
||
90 | 'retry_header' => self::RETRY_HEADER, |
||
91 | |||
92 | // The retry after header key |
||
93 | 'retry_after_header' => self::RETRY_AFTER_HEADER, |
||
94 | |||
95 | // Date format |
||
96 | 'retry_after_date_format' => self::DATE_FORMAT |
||
97 | ]; |
||
98 | |||
99 | /** |
||
100 | * @var callable |
||
101 | */ |
||
102 | private $nextHandler; |
||
103 | |||
104 | /** |
||
105 | * Provides a closure that can be pushed onto the handler stack |
||
106 | * |
||
107 | 75 | * Example: |
|
108 | * <code>$handlerStack->push(GuzzleRetryMiddleware::factory());</code> |
||
109 | * |
||
110 | 75 | * @param array<mixed> $defaultOptions |
|
111 | 75 | * @return Closure |
|
112 | */ |
||
113 | public static function factory(array $defaultOptions = []): Closure |
||
119 | |||
120 | 78 | /** |
|
121 | * GuzzleRetryMiddleware constructor. |
||
122 | 78 | * |
|
123 | 78 | * @param callable $nextHandler |
|
124 | 78 | * @param array<mixed> $defaultOptions |
|
125 | */ |
||
126 | final public function __construct(callable $nextHandler, array $defaultOptions = []) |
||
131 | 75 | ||
132 | /** |
||
133 | * @param RequestInterface $request |
||
134 | 75 | * @param array<mixed> $options |
|
135 | * @return Promise |
||
136 | */ |
||
137 | 75 | public function __invoke(RequestInterface $request, array $options): Promise |
|
154 | |||
155 | /** |
||
156 | * No exceptions were thrown during processing |
||
157 | * |
||
158 | * Depending on where this middleware is in the stack, the response could still |
||
159 | * be unsuccessful (e.g. 429 or 503), so check to see if it should be retried |
||
160 | 75 | * |
|
161 | * @param RequestInterface $request |
||
162 | * @param array<mixed> $options |
||
163 | 63 | * @return callable |
|
164 | 48 | */ |
|
165 | 63 | protected function onFulfilled(RequestInterface $request, array $options): callable |
|
173 | |||
174 | /** |
||
175 | * An exception or error was thrown during processing |
||
176 | * |
||
177 | * If the reason is a BadResponseException exception, check to see if |
||
178 | * the request can be retried. Otherwise, pass it on. |
||
179 | 75 | * |
|
180 | * @param RequestInterface $request |
||
181 | * @param array<mixed> $options |
||
182 | * @return callable |
||
183 | 18 | */ |
|
184 | 3 | protected function onRejected(RequestInterface $request, array $options): callable |
|
209 | 12 | ||
210 | 12 | /** |
|
211 | * Decide whether or not to retry on connect exception |
||
212 | * |
||
213 | * @param array<mixed> $options |
||
214 | * @return bool |
||
215 | */ |
||
216 | protected function shouldRetryConnectException(array $options): bool |
||
222 | |||
223 | /** |
||
224 | * Check to see if a request can be retried |
||
225 | 63 | * |
|
226 | * This checks two things: |
||
227 | 63 | * |
|
228 | * 1. The response status code against the status codes that should be retried |
||
229 | 21 | * 2. The number of attempts made thus far for this request |
|
230 | 63 | * |
|
231 | 63 | * @param array<mixed> $options |
|
232 | 63 | * @param ResponseInterface|null $response |
|
233 | 18 | * @return bool TRUE if the response should be retried, FALSE if not |
|
234 | */ |
||
235 | protected function shouldRetryHttpResponse(array $options, ?ResponseInterface $response = null): bool |
||
252 | 66 | ||
253 | /** |
||
254 | 66 | * Count the number of retries remaining. Always returns 0 or greater. |
|
255 | * |
||
256 | * @param array<mixed> $options |
||
257 | * @return int |
||
258 | */ |
||
259 | protected function countRemainingRetries(array $options): int |
||
269 | |||
270 | 57 | /** |
|
271 | * Retry the request |
||
272 | * |
||
273 | 57 | * Increments the retry count, determines the delay (timeout), executes callbacks, sleeps, and re-send the request |
|
274 | * |
||
275 | * @param RequestInterface $request |
||
276 | 57 | * @param array<mixed> $options |
|
277 | * @param ResponseInterface|null $response |
||
278 | 48 | * @return Promise |
|
279 | */ |
||
280 | 48 | protected function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null): Promise |
|
308 | |||
309 | /** |
||
310 | 3 | * @param array<mixed> $options |
|
311 | * @param ResponseInterface $response |
||
312 | * @return ResponseInterface |
||
313 | */ |
||
314 | protected function returnResponse(array $options, ResponseInterface $response): ResponseInterface |
||
322 | |||
323 | 57 | /** |
|
324 | * Determine the delay timeout |
||
325 | 57 | * |
|
326 | * Attempts to read and interpret the configured retry after header, or defaults |
||
327 | 3 | * to a built-in incremental back-off algorithm. |
|
328 | 3 | * |
|
329 | 3 | * @param array<mixed> $options |
|
330 | * @param ResponseInterface|null $response |
||
331 | * @return float Delay timeout, in seconds |
||
332 | 54 | */ |
|
333 | protected function determineDelayTimeout(array $options, ?ResponseInterface $response = null): float |
||
363 | |||
364 | 3 | /** |
|
365 | * Attempt to derive the timeout from the `Retry-After` (or custom) header value |
||
366 | * |
||
367 | * The spec allows the header value to either be a number of seconds or a datetime. |
||
368 | * |
||
369 | * @param string $headerValue |
||
370 | * @param string $dateFormat |
||
371 | * @return float|null The number of seconds to wait, or NULL if unsuccessful (invalid header) |
||
372 | */ |
||
373 | protected function deriveTimeoutFromHeader(string $headerValue, string $dateFormat = self::DATE_FORMAT): ?float |
||
385 | } |
||
386 |
This function has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.