Subversion Repositories php-qbpwcf

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 liveuser 1
<?php
2
 
3
namespace React\Dns\Query;
4
 
5
use React\Promise\CancellablePromiseInterface;
6
use React\Promise\Deferred;
7
use React\Promise\PromiseInterface;
8
 
9
final class RetryExecutor implements ExecutorInterface
10
{
11
    private $executor;
12
    private $retries;
13
 
14
    public function __construct(ExecutorInterface $executor, $retries = 2)
15
    {
16
        $this->executor = $executor;
17
        $this->retries = $retries;
18
    }
19
 
20
    public function query(Query $query)
21
    {
22
        return $this->tryQuery($query, $this->retries);
23
    }
24
 
25
    public function tryQuery(Query $query, $retries)
26
    {
27
        $deferred = new Deferred(function () use (&$promise) {
28
            if ($promise instanceof CancellablePromiseInterface || (!\interface_exists('React\Promise\CancellablePromiseInterface') && \method_exists($promise, 'cancel'))) {
29
                $promise->cancel();
30
            }
31
        });
32
 
33
        $success = function ($value) use ($deferred, &$errorback) {
34
            $errorback = null;
35
            $deferred->resolve($value);
36
        };
37
 
38
        $executor = $this->executor;
39
        $errorback = function ($e) use ($deferred, &$promise, $query, $success, &$errorback, &$retries, $executor) {
40
            if (!$e instanceof TimeoutException) {
41
                $errorback = null;
42
                $deferred->reject($e);
43
            } elseif ($retries <= 0) {
44
                $errorback = null;
45
                $deferred->reject($e = new \RuntimeException(
46
                    'DNS query for ' . $query->name . ' failed: too many retries',
47
                    0,
48
                    $e
49
                ));
50
 
51
                // avoid garbage references by replacing all closures in call stack.
52
                // what a lovely piece of code!
53
                $r = new \ReflectionProperty('Exception', 'trace');
54
                $r->setAccessible(true);
55
                $trace = $r->getValue($e);
56
 
57
                // Exception trace arguments are not available on some PHP 7.4 installs
58
                // @codeCoverageIgnoreStart
59
                foreach ($trace as &$one) {
60
                    if (isset($one['args'])) {
61
                        foreach ($one['args'] as &$arg) {
62
                            if ($arg instanceof \Closure) {
63
                                $arg = 'Object(' . \get_class($arg) . ')';
64
                            }
65
                        }
66
                    }
67
                }
68
                // @codeCoverageIgnoreEnd
69
                $r->setValue($e, $trace);
70
            } else {
71
                --$retries;
72
                $promise = $executor->query($query)->then(
73
                    $success,
74
                    $errorback
75
                );
76
            }
77
        };
78
 
79
        $promise = $this->executor->query($query)->then(
80
            $success,
81
            $errorback
82
        );
83
 
84
        return $deferred->promise();
85
    }
86
}