Я использую Guzzle для извлечения большого количества URL-адресов параллельно (или асинхронно), используя бассейн:
$client = new GuzzleHttp\Client([
'base_url' => 'http://httpbin.org',
]);
$requests = [];
for ($i = 0; $i < 8; ++$i) {
$requests[] = $client->createRequest('GET', '/get');
}
$pool = new GuzzleHttp\Pool($client, $requests, [
'pool_size' => 4,
'complete' => function (GuzzleHttp\Event\CompleteEvent $event) {
var_dump($event->getRequest()->getUrl());
},
]);
$pool->wait();
var_dump(count($requests));
Если я запускаю выше в консоли, он отображает ожидаемый результат:
string(22) "http://httpbin.org/get"string(22) "http://httpbin.org/get"string(22) "http://httpbin.org/get"string(22) "http://httpbin.org/get"string(22) "http://httpbin.org/get"string(22) "http://httpbin.org/get"string(22) "http://httpbin.org/get"string(22) "http://httpbin.org/get"int(8)
Теперь я хотел бы иметь возможность добавлять дополнительные запросы в тот же пул на основе некоторого условия, я считаю, что это поведение обычно известно как скользящие [параллельные] запросы, но после прочтения и перечитывания документации мне так и не удалось это выяснить. Вот что я попробовал:
$client = new GuzzleHttp\Client([
'base_url' => 'http://httpbin.org',
]);
$requests = [];
for ($i = 0; $i < 8; ++$i) {
$requests[] = $client->createRequest('GET', '/get');
}
$i = 0;
$pool = new GuzzleHttp\Pool($client, $requests, [
'pool_size' => 4,
'complete' => function (GuzzleHttp\Event\CompleteEvent $event) use (&$i, $client, &$requests) {
var_dump($event->getRequest()->getUrl());
if (++$i % 3 == 0) {
$requests[] = $client->createRequest('GET', '/ip');
}
},
]);
$pool->wait();
var_dump(count($requests));
Каждый третий запрос /get
следует добавить новый запрос к /ip
, $requests
массив на самом деле растет (до 10 элементов, а не 11, как и следовало ожидать), но запросы никогда не выполняются. Есть ли способ заставить пул Guzzle выполнять запросы после инициализации?
Возможно, см. Мой комментарий на Проблема с жадностью Предложения для GuzzleHttp \ Pool # 946 для полного примера или этой сути для более глубокого примера сравнения между генератор, повтор и последовательная отправка с жадным.
Что касается вашего примера, смотрите мои встроенные комментарии:
$client = new GuzzleHttp\Client([
'base_url' => 'http://httpbin.org',
]);
$requests = [];
for ($i = 0; $i < 8; ++$i) {
$requests[] = $client->createRequest('GET', '/get');
}
$generator = new ArrayIterator($requests); // use an iterator instead of an array
$i = 0;
$pool = new GuzzleHttp\Pool($client, $generator, [ // use the iterator in the pool
'pool_size' => 4,
'complete' => function (GuzzleHttp\Event\CompleteEvent $event) use (&$i, $client, &$generator) {
var_dump($event->getRequest()->getUrl());
if (++$i % 3 == 0) {
$generator->append($client->createRequest('GET', '/ip')); // append new requests on the fly
}
},
]);
$pool->wait();
Это дает ожидаемый результат:
string(22) "http://httpbin.org/get"string(22) "http://httpbin.org/get"string(22) "http://httpbin.org/get"string(22) "http://httpbin.org/get"string(22) "http://httpbin.org/get"string(22) "http://httpbin.org/get"string(22) "http://httpbin.org/get"string(22) "http://httpbin.org/get"string(21) "http://httpbin.org/ip"string(21) "http://httpbin.org/ip"string(21) "http://httpbin.org/ip"
Обратите внимание, что запросы получают добавлено в конце. Это противоречит принципам AbstractRetryableEvent :: повторная попытка который будет сжимать повторную попытку где-то посередине между текущей очередью, а не добавлять ее в конце.
Других решений пока нет …