Last active
December 28, 2020 05:21
-
-
Save alexeyshockov/cf20fd85d908ac30e295d0fc4d27be5c to your computer and use it in GitHub Desktop.
Dynamic request list with Guzzle (see https://stackoverflow.com/questions/42754389/guzzle-pool-wait-for-requests/43525426#43525426 for details)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace GuzzleDynamicRequests; | |
require __DIR__ . '/vendor/autoload.php'; | |
use GuzzleHttp\Client; | |
use GuzzleHttp\Psr7\Response; | |
// Do not extend IteratorIterator, because it cashes the return values somehow! | |
class MapIterator implements \Iterator | |
{ | |
/** | |
* @var \Iterator | |
*/ | |
private $inner; | |
private $handler; | |
public function __construct(\Iterator $inner, callable $handler) | |
{ | |
$this->inner = $inner; | |
$this->handler = $handler; | |
} | |
public function next() | |
{ | |
$this->inner->next(); | |
} | |
public function current() | |
{ | |
return call_user_func($this->handler, $this->inner->current(), $this->inner); | |
} | |
public function rewind() | |
{ | |
$this->inner->rewind(); | |
} | |
public function key() | |
{ | |
return $this->inner->key(); | |
} | |
public function valid() | |
{ | |
return $this->inner->valid(); | |
} | |
} | |
// Do not extend IteratorIterator, because it cashes the return values somehow! | |
class ExpectingIterator implements \Iterator | |
{ | |
/** | |
* @var \Iterator | |
*/ | |
private $inner; | |
private $wasValid; | |
public function __construct(\Iterator $inner) | |
{ | |
$this->inner = $inner; | |
} | |
public function next() | |
{ | |
if (!$this->wasValid && $this->valid()) { | |
// Just do nothing, because the inner iterator has became valid. | |
} else { | |
$this->inner->next(); | |
} | |
$this->wasValid = $this->valid(); | |
} | |
public function current() | |
{ | |
return $this->inner->current(); | |
} | |
public function rewind() | |
{ | |
$this->inner->rewind(); | |
$this->wasValid = $this->valid(); | |
} | |
public function key() | |
{ | |
return $this->inner->key(); | |
} | |
public function valid() | |
{ | |
return $this->inner->valid(); | |
} | |
} | |
// Just for the example, to show the dynamic addition. | |
$next = new \SplDoublyLinkedList(); | |
$next->push('http://yandex.ru'); | |
$next->push('http://yahoo.com'); | |
$next->push('http://rambler.com'); | |
$next->push('http://bbc.co.uk'); | |
$next->push('http://facebook.com'); | |
$next->push('http://feedly.com'); | |
$httpClient = new Client(); | |
// MapIterator is just better for readability. | |
$generator = new MapIterator( | |
// Initial data. This object will be always passed as the second parameter to the callback below | |
new \ArrayIterator(['http://google.com']), | |
function ($request, $array) use ($httpClient, $next) { | |
return $httpClient->requestAsync('GET', $request) | |
->then(function (Response $response) use ($request, $array, $next) { | |
// The status code for example. | |
echo $request . ': ' . $response->getStatusCode() . PHP_EOL; | |
// New requests. | |
$array->append($next->shift()); | |
$array->append($next->shift()); | |
}); | |
} | |
); | |
// The "magic". | |
$generator = new ExpectingIterator($generator); | |
// And the concurrent runner. | |
$promise = \GuzzleHttp\Promise\each_limit($generator, 5); | |
$promise->wait(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment