Request::call()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Dazzle\Channel\Extra;
4
5
use Dazzle\Channel\Protocol\ProtocolInterface;
6
use Dazzle\Channel\Channel;
7
use Dazzle\Channel\ChannelInterface;
8
use Dazzle\Promise\Promise;
9
use Dazzle\Promise\PromiseInterface;
10
use Dazzle\Util\Support\TimeSupport;
11
use Dazzle\Throwable\Exception\Runtime\TimeoutException;
12
use Dazzle\Throwable\Exception\System\TaskIncompleteException;
13
use Dazzle\Throwable\ThrowableProxy;
14
use Error;
15
use Exception;
16
17
class Request
18
{
19
    /**
20
     * @var ChannelInterface
21
     */
22
    protected $channel;
23
24
    /**
25
     * @var string
26
     */
27
    protected $name;
28
29
    /**
30
     * @var ProtocolInterface|string
31
     */
32
    protected $message;
33
34
    /**
35
     * @var float
36
     */
37
    protected $params;
38
39
    /**
40
     * @var int
41
     */
42
    protected $counter;
43
44
    /**
45
     * @param ChannelInterface $channel
46
     * @param string $name
47
     * @param string|ProtocolInterface $message
48
     * @param mixed[] $params
49
     */
50 17
    public function __construct($channel, $name, $message, $params = [])
51
    {
52 17
        $this->channel = $channel;
53 17
        $this->name = $name;
54 17
        $this->message = ($message instanceof ProtocolInterface) ? $message : $this->channel->createProtocol($message);
55 17
        $this->params = [
0 ignored issues
show
Documentation Bug introduced by
It seems like array('timeout' => isset...triesInterval'] : 0.25) of type array<string,*,{"timeout..."retriesInterval":"*"}> is incompatible with the declared type double of property $params.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
56 17
            'timeout'           => isset($params['timeout']) ? $params['timeout'] : 2.0,
57 17
            'retriesLimit'      => isset($params['retriesLimit']) ? $params['retriesLimit'] : 10,
58 17
            'retriesInterval'   => isset($params['retriesInterval']) ? $params['retriesInterval'] : 0.25
59
        ];
60 17
        $this->counter = 1;
61 17
        $this->message->setTimestamp(
62 17
            TimeSupport::now() + ($this->params['retriesInterval'] + $this->params['timeout']) * 1e3 * $this->params['retriesLimit'],
63 17
            true
64
        );
65 17
    }
66
67
    /**
68
     *
69
     */
70 6
    public function __destruct()
71
    {
72 6
        unset($this->channel);
73 6
        unset($this->name);
74 6
        unset($this->message);
75 6
        unset($this->params);
76 6
        unset($this->counter);
77 6
    }
78
79
    /**
80
     * Send the prepared request.
81
     *
82
     * @return PromiseInterface
83
     * @resolves mixed
84
     * @rejects Error|Exception|string|null
85
     * @cancels Error|Exception|string|null
86
     */
87 1
    public function __invoke()
88
    {
89 1
        return $this->send(new Promise());
90
    }
91
92
    /**
93
     * Send the prepared request.
94
     *
95
     * @return PromiseInterface
96
     * @resolves mixed
97
     * @rejects Error|Exception|string|null
98
     * @cancels Error|Exception|string|null
99
     */
100 1
    public function call()
101
    {
102 1
        return $this->send(new Promise());
103
    }
104
105
    /**
106
     * Send the request using passed Promise.
107
     *
108
     * @param PromiseInterface $promise
109
     * @return PromiseInterface
110
     */
111 5
    protected function send(PromiseInterface $promise)
112
    {
113 5
        if (!$promise->isPending())
114
        {
115 1
            return $promise;
116
        }
117
118 4
        $this->channel->send(
119 4
            $this->name,
120 4
            $this->message,
121 4
            Channel::MODE_STANDARD,
122
            function($value) use($promise) {
123 1
                $promise->resolve($value);
124 4
            },
125
            function($ex) use($promise) {
126 1
                $promise->reject($ex);
127 4
            },
128
            function($ex) use($promise) {
129 1
                $this->retryOrReset($promise, $ex);
130 4
            },
131 4
            $this->params['timeout']
132
        );
133
134 4
        return $promise;
135
    }
136
137
    /**
138
     * @param PromiseInterface $promise
139
     * @param Error|Exception|ThrowableProxy $ex
140
     */
141 4
    protected function retryOrReset(PromiseInterface $promise, $ex)
142
    {
143 4
        if ($ex instanceof TaskIncompleteException)
144
        {
145 1
            $this->counter = 1;
146
            $this->channel->getLoop()->onTick(function() use($promise) {
147 1
                $this->send($promise);
148 1
            });
149 1
            return;
150
        }
151
152 3
        $this->retry($promise);
153 3
    }
154
155
    /**
156
     * @param PromiseInterface $promise
157
     */
158 3
    private function retry(PromiseInterface $promise)
159
    {
160 3
        if ($this->counter >= $this->params['retriesLimit'])
161
        {
162 1
            $promise->reject(
163 1
                new ThrowableProxy(new TimeoutException('No response was received during specified timeout.'))
164
            );
165
        }
166 2
        else if ($this->params['retriesInterval'] > 0)
167
        {
168 1
            $this->counter++;
169
            $this->channel->getLoop()->addTimer($this->params['retriesInterval'], function() use($promise) {
170 1
                $this->send($promise);
171 1
            });
172
        }
173
        else
174
        {
175 1
            $this->counter++;
176 1
            $this->channel->getLoop()->onTick(function() use($promise) {
177 1
                $this->send($promise);
178 1
            });
179
        }
180 3
    }
181
}
182