-
Notifications
You must be signed in to change notification settings - Fork 0
/
WaitLoop.php
88 lines (72 loc) · 2.68 KB
/
WaitLoop.php
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
<?php
declare(strict_types=1);
namespace Manyou\PromiseHttpClient;
use GuzzleHttp\Promise\Utils;
use SplObjectStorage;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;
use Throwable;
use function max;
use function microtime;
use function min;
/**
* @internal
*
* @see \Symfony\Component\HttpClient\Internal\HttplugWaitLoop
*
* @author Nicolas Grekas <[email protected]>
*/
final class WaitLoop
{
public function __construct(private HttpClientInterface $client, private SplObjectStorage $promisePool)
{
}
public function wait(?ResponseInterface $pendingResponse, ?float $maxDuration = null, ?float $idleTimeout = null): int
{
$guzzleQueue = Utils::queue();
if (0.0 === $remainingDuration = $maxDuration) {
$idleTimeout = 0.0;
} elseif (null !== $maxDuration) {
$startTime = microtime(true);
$idleTimeout = max(0.0, min($maxDuration / 5, $idleTimeout ?? $maxDuration));
}
do {
foreach ($this->client->stream($this->promisePool, $idleTimeout) as $response => $chunk) {
try {
if (null !== $maxDuration && $chunk->isTimeout()) {
goto check_duration;
}
if ($chunk->isFirst()) {
// Deactivate throwing on 3/4/5xx
$response->getStatusCode();
}
if (! $chunk->isLast()) {
goto check_duration;
}
if ($promise = $this->promisePool[$response] ?? null) {
unset($this->promisePool[$response]);
$promise->resolve($response);
}
} catch (Throwable $e) {
if ($promise = $this->promisePool[$response] ?? null) {
unset($this->promisePool[$response]);
$promise->reject($e);
}
}
$guzzleQueue->run();
if ($pendingResponse === $response) {
return $this->promisePool->count();
}
check_duration:
if (null !== $maxDuration && $idleTimeout && $idleTimeout > $remainingDuration = max(0.0, $maxDuration - microtime(true) + $startTime)) {
$idleTimeout = $remainingDuration / 5;
break;
}
}
if (! $count = $this->promisePool->count()) {
return 0;
}
} while (null === $maxDuration || 0 < $remainingDuration);
return $count;
}
}