Lines 90.32% 28 / 31
Methods 25.00% 1 / 4
Classes 0.00% 0 / 1
Name Lines Methods CRAP
 decider 93.33% 14 / 15 0.00% 0 / 1 5.01
 delay 0.00% 0 / 1 0.00% 0 / 1 2
 delayMs 100.00% 6 / 6 100.00% 1 / 1 3
 retryAfterMs 88.88% 8 / 9 0.00% 0 / 1 4.02
18final class RetryPolicy
19{
20    public static function decider(int $maxRetries): callable
21    {
22        return static function (
23            int $retries,
24            RequestInterface $request,
25            ?ResponseInterface $response = null,
26            ?\Throwable $exception = null,
27        ) use ($maxRetries): bool {
28            if ($retries >= $maxRetries) {
29                return false;
30            }
31            if ($exception instanceof ConnectException) {
32                return true;
33            }
34            if (null !== $response) {
35                $status = $response->getStatusCode();
36
37                return $status >= 500 || 429 === $status;
38            }
39
40            return false;
41        };
42    }
43
44    public static function delay(): callable
45    {
46        return self::delayMs(...);
47    }
48
49    public static function delayMs(int $retries, ?ResponseInterface $response = null): int
50    {
51        if (null !== $response) {
52            $retryAfterMs = self::retryAfterMs($response);
53            if (null !== $retryAfterMs) {
54                return $retryAfterMs;
55            }
56        }
57
58        $base = 100 * 2 ** ($retries - 1);
59
60        return (int) ($base + random_int(0, (int) $base));
61    }
62
63    private static function retryAfterMs(ResponseInterface $response): ?int
64    {
65        $retryAfter = $response->getHeaderLine('Retry-After');
66        if ('' === $retryAfter) {
67            return null;
68        }
69
70        if (is_numeric($retryAfter)) {
71            return max((int) ((float) $retryAfter * 1000), 0);
72        }
73
74        $when = strtotime($retryAfter);
75        if (false === $when) {
76            return null;
77        }
78
79        return max(($when - time()) * 1000, 0);
80    }
81}