Example #1
0
 /**
  * Start crawling.
  *
  * @param int $chunk
  *
  * @return \GuzzleHttp\Promise\PromiseInterface
  */
 public function start($chunk = 5)
 {
     $this->dispatchStart();
     // We need to use a double loop of generators here, because
     // if $chunk is greater than the number of items in the queue,
     // the requestWorkerFn exits the generator loop before any new
     // requests can be added by processing and cannot be restarted.
     // The outer generator ($gen) restarts the processing in that case.
     $gen = function () use($chunk) {
         while ($this->queue->count() > 0) {
             $inner = new EachPromise($this->getRequestWorkerFn(), ['concurrency' => $chunk]);
             (yield $inner->promise());
         }
     };
     $outer = new EachPromise($gen(), ['concurrency' => 1]);
     $finish = function ($results) {
         $this->dispatchFinish();
         return $results;
     };
     return $outer->promise()->then($finish, $finish);
 }
 /**
  * @return \GuzzleHttp\Promise\PromiseInterface
  */
 public function promise()
 {
     return $this->each->promise();
 }
 public function testDoesNotCallNextOnIteratorUntilNeededWhenAsync()
 {
     $firstPromise = new Promise();
     $pending = [$firstPromise];
     $values = [$firstPromise];
     $results = [];
     $remaining = 9;
     $iter = function () use(&$values) {
         while ($value = array_pop($values)) {
             (yield $value);
         }
     };
     $each = new EachPromise($iter(), ['concurrency' => 1, 'fulfilled' => function ($r) use(&$results, &$values, &$remaining, &$pending) {
         $results[] = $r;
         if ($remaining-- > 0) {
             $pending[] = $values[] = new Promise();
         }
     }]);
     $i = 0;
     $each->promise();
     while ($promise = array_pop($pending)) {
         $promise->resolve($i++);
         P\queue()->run();
     }
     $this->assertEquals(range(0, 9), $results);
 }
 public function testRejectsAggregateWhenNextThrows()
 {
     $iter = function () {
         (yield 'a');
         throw new \Exception('Failure');
     };
     $each = new EachPromise($iter());
     $p = $each->promise();
     $e = null;
     $received = null;
     $p->then(null, function ($reason) use(&$e) {
         $e = $reason;
     });
     P\queue()->run();
     $this->assertInstanceOf('Exception', $e);
     $this->assertEquals('Failure', $e->getMessage());
 }
Example #5
0
 public function testMutexPreventsGeneratorRecursion()
 {
     $results = $promises = [];
     for ($i = 0; $i < 20; $i++) {
         $p = $this->createSelfResolvingPromise($i);
         $pending[] = $p;
         $promises[] = $p;
     }
     $iter = function () use(&$promises, &$pending) {
         foreach ($promises as $promise) {
             // Resolve a promises, which will trigger the then() function,
             // which would cause the EachPromise to try to add more
             // promises to the queue. Without a lock, this would trigger
             // a "Cannot resume an already running generator" fatal error.
             if ($p = array_pop($pending)) {
                 $p->wait();
             }
             (yield $promise);
         }
     };
     $each = new EachPromise($iter(), ['concurrency' => 5, 'fulfilled' => function ($r) use(&$results, &$pending) {
         $results[] = $r;
     }]);
     $each->promise()->wait();
     $this->assertCount(20, $results);
 }