Issues (46)

src/Concerns/RetriesHttpRequests.php (3 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cerbero\LazyJsonPages\Concerns;
6
7
use Cerbero\LazyJsonPages\Exceptions\OutOfAttemptsException;
8
use Closure;
9
use Generator;
10
use GuzzleHttp\Exception\TransferException;
11
use Illuminate\Support\LazyCollection;
12
13
/**
14
 * The trait to retry HTTP requests when they fail.
15
 *
16
 * @property-read \Cerbero\LazyJsonPages\Data\Config $config
17
 * @property-read \Cerbero\LazyJsonPages\Services\Book $book
18
 */
19
trait RetriesHttpRequests
20
{
21
    /**
22
     * Retry to yield HTTP responses from the given callback.
23
     *
24
     * @template TGen of Generator
25
     * @param Closure(): TGen $callback
26
     * @return TGen
0 ignored issues
show
The type Cerbero\LazyJsonPages\Concerns\TGen was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
27
     */
28 41
    protected function retry(Closure $callback): Generator
29
    {
30 41
        $attempt = 0;
31 41
        $remainingAttempts = $this->config->attempts;
32
33
        do {
34 41
            $failed = false;
35 41
            ++$attempt;
36 41
            --$remainingAttempts;
37
38
            try {
39 41
                yield from $callback();
40 2
            } catch (TransferException $e) {
41 1
                $failed = true;
42
43 1
                if ($remainingAttempts > 0) {
44 1
                    $this->backoff($attempt);
45
                } else {
46 1
                    $this->outOfAttempts($e);
47
                }
48
            }
49 40
        } while ($failed && $remainingAttempts > 0);
50
    }
51
52
    /**
53
     * Execute the backoff strategy.
54
     */
55 1
    protected function backoff(int $attempt): void
56
    {
57 1
        $backoff = $this->config->backoff ?: fn(int $attempt) => $attempt ** 2 * 100;
58
59 1
        usleep($backoff($attempt) * 1000);
60
    }
61
62
    /**
63
     * Throw the out of attempts exception.
64
     */
65 1
    protected function outOfAttempts(TransferException $e): never
66
    {
67 1
        throw new OutOfAttemptsException($e, $this->book->pullFailedPages(), new LazyCollection(function () {
0 ignored issues
show
function(...) { /* ... */ } of type callable is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $source of Illuminate\Support\LazyCollection::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

67
        throw new OutOfAttemptsException($e, $this->book->pullFailedPages(), new LazyCollection(/** @scrutinizer ignore-type */ function () {
Loading history...
68 1
            foreach ($this->book->pullPages() as $page) {
69 1
                yield from $this->yieldItemsFrom($page);
0 ignored issues
show
It seems like yieldItemsFrom() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

69
                yield from $this->/** @scrutinizer ignore-call */ yieldItemsFrom($page);
Loading history...
70
            }
71 1
        }));
72
    }
73
}
74