-
-
Save oleksandr-roskovynskyi/7d6147bd342dd8f07bf3ab94aedffc06 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 hidden or 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