-
Notifications
You must be signed in to change notification settings - Fork 53
Expand file tree
/
Copy pathHttpClientPoolItem.php
More file actions
175 lines (147 loc) · 4.71 KB
/
HttpClientPoolItem.php
File metadata and controls
175 lines (147 loc) · 4.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
<?php
declare(strict_types=1);
namespace Http\Client\Common\HttpClientPool;
use Http\Client\Common\FlexibleHttpClient;
use Http\Client\Exception;
use Http\Client\HttpAsyncClient;
use Http\Client\HttpClient;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
/**
* A HttpClientPoolItem represent a HttpClient inside a Pool.
*
* It is disabled when a request failed and can be reenabled after a certain number of seconds.
* It also keep tracks of the current number of open requests the client is currently being sending
* (only usable for async method).
*
* This class is used internally in the client pools and is not supposed to be used anywhere else.
*
* @final
*
* @internal
*
* @author Joel Wurtz <joel.wurtz@gmail.com>
*/
class HttpClientPoolItem implements HttpClient, HttpAsyncClient
{
/**
* @var int Number of request this client is currently sending
*/
private $sendingRequestCount = 0;
/**
* @var \DateTime|null Time when this client has been disabled or null if enable
*/
private $disabledAt;
/**
* Number of seconds until this client is enabled again after an error.
*
* null: never reenable this client.
*
* @var int|null
*/
private $reenableAfter;
/**
* @var FlexibleHttpClient A http client responding to async and sync request
*/
private $client;
/**
* @param ClientInterface|HttpAsyncClient $client
* @param int|null $reenableAfter Number of seconds until this client is enabled again after an error
*/
public function __construct($client, ?int $reenableAfter = null)
{
if (!$client instanceof ClientInterface && !$client instanceof HttpAsyncClient) {
throw new \TypeError(
sprintf('%s::__construct(): Argument #1 ($client) must be of type %s|%s, %s given', self::class, ClientInterface::class, HttpAsyncClient::class, get_debug_type($client))
);
}
$this->client = new FlexibleHttpClient($client);
$this->reenableAfter = $reenableAfter;
}
public function sendRequest(RequestInterface $request): ResponseInterface
{
if ($this->isDisabled()) {
throw new Exception\RequestException('Cannot send the request as this client has been disabled', $request);
}
try {
$this->incrementRequestCount();
$response = $this->client->sendRequest($request);
$this->decrementRequestCount();
} catch (Exception $e) {
$this->disable();
$this->decrementRequestCount();
throw $e;
}
return $response;
}
public function sendAsyncRequest(RequestInterface $request)
{
if ($this->isDisabled()) {
throw new Exception\RequestException('Cannot send the request as this client has been disabled', $request);
}
$this->incrementRequestCount();
return $this->client->sendAsyncRequest($request)->then(function ($response) {
$this->decrementRequestCount();
return $response;
}, function ($exception) {
$this->disable();
$this->decrementRequestCount();
throw $exception;
});
}
/**
* Whether this client is disabled or not.
*
* If the client was disabled, calling this method checks if the client can
* be reenabled and if so enables it.
*/
public function isDisabled(): bool
{
if (null !== $this->reenableAfter && null !== $this->disabledAt) {
// Reenable after a certain time
$now = new \DateTime();
if (($now->getTimestamp() - $this->disabledAt->getTimestamp()) >= $this->reenableAfter) {
$this->enable();
return false;
}
return true;
}
return null !== $this->disabledAt;
}
/**
* Get current number of request that are currently being sent by the underlying HTTP client.
*/
public function getSendingRequestCount(): int
{
return $this->sendingRequestCount;
}
/**
* Increment the request count.
*/
private function incrementRequestCount(): void
{
++$this->sendingRequestCount;
}
/**
* Decrement the request count.
*/
private function decrementRequestCount(): void
{
--$this->sendingRequestCount;
}
/**
* Enable the current client.
*/
private function enable(): void
{
$this->disabledAt = null;
}
/**
* Disable the current client.
*/
private function disable(): void
{
$this->disabledAt = new \DateTime('now');
}
}