Completed
Pull Request — master (#49)
by Joel
04:06
created

HttpClientPoolItem::sendRequest()   A

Complexity

Conditions 3
Paths 5

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 19
ccs 11
cts 11
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 12
nc 5
nop 1
crap 3
1
<?php
2
3
namespace Http\Client\Common;
4
5
use Http\Client\HttpAsyncClient;
6
use Http\Client\HttpClient;
7
use Psr\Http\Message\RequestInterface;
8
use Http\Client\Exception;
9
10
/**
11
 * A HttpClientPoolItem represent a HttpClient inside a Pool.
12
 *
13
 * It is disabled when a request failed and can be reenable after a certain number of seconds
14
 * It also keep tracks of the current number of request the client is currently sending (only usable for async method)
15
 *
16
 * @author Joel Wurtz <[email protected]>
17
 */
18
class HttpClientPoolItem implements HttpClient, HttpAsyncClient
19
{
20
    /** @var int Number of request this client is currently sending */
21
    private $sendingRequestCount = 0;
22
23
    /** @var \DateTime|null Time when this client has been disabled or null if enable */
24
    private $disabledAt;
25
26
    /** @var int|null Number of seconds after this client is reenable, by default null: never reenable this client */
27
    private $reenableAfter;
28
29
    /** @var FlexibleHttpClient A http client responding to async and sync request */
30
    private $client;
31
32
    /**
33
     * {@inheritdoc}
34
     *
35
     * @param null|int $reenableAfter Number of seconds after this client is reenable
36
     */
37 23
    public function __construct($client, $reenableAfter = null)
38
    {
39 23
        $this->client = new FlexibleHttpClient($client);
40 23
        $this->reenableAfter = $reenableAfter;
41 23
    }
42
43
    /**
44
     * {@inheritdoc}
45
     */
46 13
    public function sendRequest(RequestInterface $request)
47
    {
48 13
        if ($this->isDisabled()) {
49 1
            throw new Exception\RequestException('Cannot send the request as this client has been disabled', $request);
50
        }
51
52
        try {
53 13
            $this->incrementRequestCount();
54 13
            $response = $this->client->sendRequest($request);
55 5
            $this->decrementRequestCount();
56 13
        } catch (Exception $e) {
57 8
            $this->disable();
58 8
            $this->decrementRequestCount();
59
60 8
            throw $e;
61
        }
62
63 5
        return $response;
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69 8
    public function sendAsyncRequest(RequestInterface $request)
70
    {
71 8
        if ($this->isDisabled()) {
72 1
            throw new Exception\RequestException('Cannot send the request as this client has been disabled', $request);
73
        }
74
75 8
        $this->incrementRequestCount();
76
77
        return $this->client->sendAsyncRequest($request)->then(function ($response) {
78 1
            $this->decrementRequestCount();
79
80 1
            return $response;
81 8
        }, function ($exception) {
82 2
            $this->disable();
83 2
            $this->decrementRequestCount();
84
85 2
            throw $exception;
86 8
        });
87
    }
88
89
    /**
90
     * Whether this client is disabled or not.
91
     *
92
     * Will also reactivate this client if possible
93
     *
94
     * @return bool
95
     */
96 21
    public function isDisabled()
97
    {
98 21
        $disabledAt = $this->getDisabledAt();
99
100 21
        if (null !== $this->reenableAfter && null !== $disabledAt) {
101
            // Reenable after a certain time
102 5
            $now = new \DateTime();
103
104 5
            if (($now->getTimestamp() - $disabledAt->getTimestamp()) >= $this->reenableAfter) {
105 5
                $this->enable();
106
107 5
                return false;
108
            }
109
110
            return true;
111
        }
112
113 21
        return null !== $disabledAt;
114
    }
115
116
    /**
117
     * Get current number of request that is send by the underlying http client.
118
     *
119
     * @return int
120
     */
121 2
    public function getSendingRequestCount()
122
    {
123 2
        return $this->sendingRequestCount;
124
    }
125
126
    /**
127
     * Return when this client has been disabled or null if it's enabled.
128
     *
129
     * @return \DateTime|null
130
     */
131 21
    private function getDisabledAt()
132
    {
133 21
        return $this->disabledAt;
134
    }
135
136
    /**
137
     * Increment the request count.
138
     */
139 21
    private function incrementRequestCount()
140
    {
141 21
        ++$this->sendingRequestCount;
142 21
    }
143
144
    /**
145
     * Decrement the request count.
146
     */
147 16
    private function decrementRequestCount()
148
    {
149 16
        --$this->sendingRequestCount;
150 16
    }
151
152
    /**
153
     * Enable the current client.
154
     */
155 5
    private function enable()
156
    {
157 5
        $this->disabledAt = null;
158 5
    }
159
160
    /**
161
     * Disable the current client.
162
     */
163 10
    private function disable()
164
    {
165 10
        $this->disabledAt = new \DateTime('now');
166 10
    }
167
}
168