Пример #1
1
 public function testClearsReferencesWhenResolved()
 {
     $called = false;
     $a = new Promise(function () use(&$a, &$called) {
         $a->resolve('a');
         $called = true;
     });
     $each = new EachPromise([$a], ['concurrency' => function () {
         return 1;
     }, 'fulfilled' => function () {
     }, 'rejected' => function () {
     }]);
     $each->promise()->wait();
     $this->assertNull($this->readAttribute($each, 'onFulfilled'));
     $this->assertNull($this->readAttribute($each, 'onRejected'));
     $this->assertNull($this->readAttribute($each, 'iterable'));
     $this->assertNull($this->readAttribute($each, 'pending'));
     $this->assertNull($this->readAttribute($each, 'concurrency'));
     $this->assertTrue($called);
 }
Пример #2
0
 public function __invoke(RequestInterface $request, array $options)
 {
     $fn = $this->nextHandler;
     $throttleId = isset($options['throttle_id']) ? $options['throttle_id'] : null;
     $limit = isset($options['throttle_limit']) ? $options['throttle_limit'] : null;
     if (!$throttleId || !$limit) {
         // Request is not throttled; just ignore it.
         return $fn($request, $options);
     }
     if (!isset($this->running[$throttleId])) {
         $this->running[$throttleId] = 0;
         $this->queue[$throttleId] = [];
     }
     $promise = new Promise([\GuzzleHttp\Promise\queue(), 'run']);
     if ($this->running[$throttleId] + 1 <= $limit) {
         // Queue has enough space; run this request and watch for queue size.
         ++$this->running[$throttleId];
         return $fn($request, $options)->then($this->getQueuePopper($throttleId, true), $this->getQueuePopper($throttleId, false));
     }
     // The queue is full; delay the request, and don't forget to also pop the queue.
     $this->queue[$throttleId][] = function () use($request, $options, $fn, $throttleId, $promise) {
         $promise->resolve($fn($request, $options)->then($this->getQueuePopper($throttleId, true), $this->getQueuePopper($throttleId, false)));
     };
     return $promise;
 }
Пример #3
0
 /**
  * Add optional promise to process options
  *
  * @param Process $process
  * @return Promise
  */
 private function addPromise(Process $process)
 {
     /** @var Promise $promise */
     $promise = new Promise(function () use($process, &$promise) {
         $process->wait();
         $promise->resolve($process);
     });
     $process->setOptions([ProcessQueue::PROMISE_KEY => $promise]);
     return $promise;
 }
Пример #4
0
 /**
  * @param Route $route
  * @return Promise|PromiseInterface
  * @throws \LogicException
  * @throws \InvalidArgumentException
  */
 public function request(Route $route)
 {
     $request = $this->prepareRequest($this->gitter->token, $route);
     $this->logRequest($request);
     $responsePromise = $this->client->sendAsync($request, $this->options);
     $promise = new Promise(function ($unwrap = true) use($responsePromise) {
         $responsePromise->wait($unwrap);
     });
     $responsePromise->then(function (ResponseInterface $response) use($promise) {
         $this->logResponse($response);
         $promise->resolve(json((string) $response->getBody(), true));
     });
     return $promise;
 }
Пример #5
0
 /**
  * @param \SplFileInfo|string $cwd
  * @return PromiseInterface
  */
 public function enqueue($cwd = null)
 {
     $process = $this->factory->make($cwd);
     /** @var Promise $promise */
     $promise = new Promise(function () use($process, &$promise) {
         if ($process->isStarted()) {
             $process->wait();
         }
         $process->isSuccessful() ? $promise->resolve($process) : $promise->reject($process);
     });
     $this->queue->add($process);
     $process->setOptions([ProcessQueue::PROMISE_KEY => $promise]);
     return $promise;
 }
Пример #6
0
 public function run(callable $callback, $time)
 {
     $promise = new Promise();
     $loop = Runner::getLoop();
     $loop->addTimer($time, function () use($promise, $callback) {
         if ($promise->getState() === PromiseInterface::PENDING) {
             try {
                 $promise->resolve($callback());
             } catch (\Exception $e) {
                 $promise->reject($e);
             }
         }
     });
     return $promise;
 }
 public function __invoke(RequestInterface $request, array $options)
 {
     $artaxRequest = $this->convertRequest($request, $options);
     $artaxResponsePromise = $this->artaxClient->request($artaxRequest);
     $guzzleResponsePromise = new Promise(function () use($artaxResponsePromise) {
         \Amp\wait($artaxResponsePromise);
     });
     $artaxResponsePromise->when(function ($error = null, Response $artaxResponse = null) use($request, $options, $guzzleResponsePromise) {
         if ($error) {
             $guzzleResponsePromise->reject($error);
         } else {
             $response = $this->convertResponse($artaxResponse, $request, $options);
             $guzzleResponsePromise->resolve($response);
         }
     });
     return $guzzleResponsePromise;
 }
Пример #8
0
 /**
  * Magic method which intercepts async calls, finds the sequential version, and wraps it in a
  * {@see Promise} object. In order for this to happen, the called methods need to be in the
  * following format: `createAsync`, where `create` is the sequential method being wrapped.
  *
  * @param $methodName The name of the method being invoked.
  * @param $args       The arguments to be passed to the sequential method.
  *
  * @throws \RuntimeException If method does not exist
  *
  * @return Promise
  */
 public function __call($methodName, $args)
 {
     $e = function ($name) {
         return new \RuntimeException(sprintf('%s::%s is not defined', get_class($this), $name));
     };
     if (substr($methodName, -5) === 'Async') {
         $realMethod = substr($methodName, 0, -5);
         if (!method_exists($this, $realMethod)) {
             throw $e($realMethod);
         }
         $promise = new Promise(function () use(&$promise, $realMethod, $args) {
             $value = call_user_func_array([$this, $realMethod], $args);
             $promise->resolve($value);
         });
         return $promise;
     }
     throw $e($methodName);
 }
Пример #9
0
 public function start()
 {
     $promise = new Promise([$this, 'wait']);
     $this->process->start(function ($type, $buffer) use($promise) {
         if (Process::ERR === $type) {
             $this->logger->error($buffer);
         } else {
             $this->logger->debug($buffer);
         }
         if ($promise->getState() === Promise::PENDING) {
             if (Process::ERR === $type) {
                 $promise->reject(false);
             } else {
                 $promise->resolve(true);
             }
         }
     });
     return $promise;
 }
 /**
  * @param Psr7Request $request
  * @param array       $options
  *
  * @return Promise\Promise
  */
 public function __invoke(Psr7Request $request, array $options = [])
 {
     // Create and send a Guzzle 5 request
     $guzzlePromise = $this->client->send($this->createGuzzleRequest($request, $options));
     $promise = new Promise\Promise(function () use($guzzlePromise) {
         try {
             $guzzlePromise->wait();
         } catch (\Exception $e) {
             // The promise is already delivered when the exception is
             // thrown, so don't rethrow it.
         }
     }, [$guzzlePromise, 'cancel']);
     $guzzlePromise->then([$promise, 'resolve'], [$promise, 'reject']);
     return $promise->then(function (GuzzleResponse $response) {
         // Adapt the Guzzle 5 Future to a Guzzle 6 ResponsePromise.
         return $this->createPsr7Response($response);
     }, function (Exception $exception) {
         // Reject with information about the error.
         return new Promise\RejectedPromise($this->prepareErrorData($exception));
     });
 }
Пример #11
0
 /**
  * @param  array $criteria              Criterias for querying geocoding
  * @return GuzzlePromise                The promise for guzzle request
  *
  * @throws InvalidArgumentException
  */
 public function lookup($criteria)
 {
     // TODO: Discuss criteria validation
     if (!is_array($criteria)) {
         throw new InvalidArgumentException('Criteria must be an array with keys and values');
     }
     $lookup_promise = null;
     $lookup_promise = new GuzzlePromise(function () use($criteria, &$lookup_promise) {
         $this->client_interface->sendAsync(new Request("GET", sprintf(self::GEOCODEURL, $this->response_type, $this->arrayToQueryParams($criteria))))->then(function ($response) use($lookup_promise) {
             if ($response->getStatusCode() === 200) {
                 $geo_location_response = json_decode($response->getBody());
                 if ($geo_location_response->status !== "OK") {
                     $lookup_promise->reject(sprintf("Server responded with status %s", $geo_location_response->status));
                 } else {
                     $lookup_promise->resolve(Factory::create('GoogleGeoCoder\\GeoCollection', $geo_location_response->results));
                 }
             } else {
                 $lookup_promise->reject(sprintf("Server responded with code %s", $response->getStatusCode()));
             }
         }, function ($response) use($lookup_promise) {
             $lookup_promise->reject(sprintf("Server responded with failure"));
         })->wait();
     });
     return $lookup_promise;
 }
Пример #12
0
 /**
  * @internal
  */
 public function _handleFailure($reason)
 {
     unset($this->currentPromise);
     try {
         $nextYield = $this->generator->throw(exception_for($reason));
         // The throw was caught, so keep iterating on the coroutine
         $this->nextCoroutine($nextYield);
     } catch (Exception $exception) {
         $this->result->reject($exception);
     } catch (Throwable $throwable) {
         $this->result->reject($throwable);
     }
 }
 /**
  * @test
  */
 public function it_rejects_deferred_with_runtime_exception_asynchronous_when_json_response_is_invalid()
 {
     $producerInAsyncMode = new HttpMessageProducer($this->guzzleClient, new NoOpMessageConverter(), null, true);
     $fetchDataQuery = new FetchSomething(['filter' => 'foo']);
     $psrResponse = $this->prophesize(ResponseInterface::class);
     $queryDeferred = new Deferred();
     $producerInAsyncMode($fetchDataQuery, $queryDeferred);
     //Return invalid json
     $psrResponse->getBody()->willReturn('[{"data" => "bar"');
     $this->responsePromise->resolve($psrResponse->reveal());
     //Perform next tick, required to resolve the promise when we are in async mode
     $queue = \GuzzleHttp\Promise\queue();
     $queue->run();
     $rejectionReason = null;
     $queryDeferred->promise()->otherwise(function ($reason) use(&$rejectionReason) {
         $rejectionReason = $reason;
     });
     $this->assertInstanceOf(RuntimeException::class, $rejectionReason);
 }
Пример #14
0
 public function testOtherwiseIsSugarForRejections()
 {
     $p = new Promise();
     $p->reject('foo');
     $p->otherwise(function ($v) use(&$c) {
         $c = $v;
     });
     P\queue()->run();
     $this->assertEquals($c, 'foo');
 }
Пример #15
0
 public function testCoroutineOtherwiseIntegrationTest()
 {
     $a = new P\Promise();
     $b = new P\Promise();
     $promise = P\coroutine(function () use($a, $b) {
         // Execute the pool of commands concurrently, and process errors.
         (yield $a);
         (yield $b);
     })->otherwise(function (\Exception $e) {
         // Throw errors from the operations as a specific Multipart error.
         throw new \OutOfBoundsException('a', 0, $e);
     });
     $a->resolve('a');
     $b->reject('b');
     $reason = P\inspect($promise)['reason'];
     $this->assertInstanceOf('OutOfBoundsException', $reason);
     $this->assertInstanceOf('GuzzleHttp\\Promise\\RejectionException', $reason->getPrevious());
 }
Пример #16
0
 /**
  * @param string $method
  * @param mixed  $params
  *
  * @return PromiseInterface
  */
 public function callAsync($method, $params)
 {
     $requestId = uniqid();
     $options = $this->prepareCall($method, $params, $requestId);
     $response = $this->getClient()->postAsync('', $options);
     $promise = new Promise(function ($unwrap) use($response) {
         return $response->wait($unwrap);
     }, function () use($response) {
         return $response->cancel();
     });
     $response->then(function (ResponseInterface $res) use($promise) {
         try {
             $promise->resolve($this->handleResponse($res->getBody()));
             return $res;
         } catch (\Exception $e) {
             $promise->reject($e);
             throw $e;
         }
     }, function (\Exception $reqException) use($promise, $requestId) {
         $this->logResponse($requestId, strval($reqException));
         $promise->reject($reqException);
         return $reqException;
     });
     $promise->then(function ($res) use($requestId) {
         $this->logResponse($requestId, json_encode($res));
         return $res;
     }, function ($res) use($requestId) {
         $this->logResponse($requestId, strval($res));
         return $res;
     });
     return $promise;
 }
Пример #17
0
 /**
  * @param Promise $req
  *
  * @return Promise Promise with attached transformers
  */
 private function attachTransforms(Promise $req)
 {
     $transformers = $this->getTransformers();
     return $req->then(function (Response $res) use($transformers) {
         $data = \json_decode((string) $res->getBody());
         if (is_object($data)) {
             foreach ($transformers as $transformer) {
                 $data = \call_user_func($transformer, $data);
             }
         } elseif (is_array($data)) {
             foreach ($data as $key => $val) {
                 foreach ($transformers as $transformer) {
                     $data[$key] = \call_user_func($transformer, $val);
                 }
             }
         }
         return $data;
     }, function (RequestException $e) {
     });
 }
Пример #18
0
 /**
  * @param string          $targetUrl   target url to import resource into
  * @param string          $file        path to file being loaded
  * @param OutputInterface $output      output of the command
  * @param Document        $doc         document to load
  * @param string          $host        host to import into
  * @param string          $rewriteHost string to replace with value from $host during loading
  * @param string          $rewriteTo   string to replace value from $rewriteHost with during loading
  * @param boolean         $sync        send requests syncronously
  *
  * @return Promise\Promise|null
  */
 protected function importResource($targetUrl, $file, OutputInterface $output, Document $doc, $host, $rewriteHost, $rewriteTo, $sync = false)
 {
     $content = str_replace($rewriteHost, $rewriteTo, $doc->getContent());
     $successFunc = function (ResponseInterface $response) use($output) {
         $output->writeln('<comment>Wrote ' . $response->getHeader('Link')[0] . '</comment>');
     };
     $errFunc = function (RequestException $e) use($output, $file) {
         $output->writeln('<error>' . str_pad(sprintf('Failed to write <%s> from \'%s\' with message \'%s\'', $e->getRequest()->getUri(), $file, $e->getMessage()), 140, ' ') . '</error>');
         if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
             $this->dumper->dump($this->cloner->cloneVar($this->parser->parse($e->getResponse()->getBody(), false, false, true)), function ($line, $depth) use($output) {
                 if ($depth > 0) {
                     $output->writeln('<error>' . str_pad(str_repeat('  ', $depth) . $line, 140, ' ') . '</error>');
                 }
             });
         }
     };
     if ($sync === false) {
         $promise = $this->client->requestAsync('PUT', $targetUrl, ['json' => $this->parseContent($content, $file)]);
         $promise->then($successFunc, $errFunc);
     } else {
         $promise = new Promise\Promise();
         try {
             $promise->resolve($successFunc($this->client->request('PUT', $targetUrl, ['json' => $this->parseContent($content, $file)])));
         } catch (BadResponseException $e) {
             $promise->resolve($errFunc($e));
         }
     }
     return $promise;
 }
Пример #19
0
 private function createSelfResolvingPromise($value)
 {
     $p = new Promise(function () use(&$p, $value) {
         $p->resolve($value);
     });
     return $p;
 }
 /**
  * {@inheritdoc}
  */
 public function resolve()
 {
     $this->promise->wait();
 }
Пример #21
0
echo "Username: {$username->wait()}\n";
// if you wanted to pass things all the way into a template you could do a trick like
use GuzzleHttp\Promise\PromiseInterface;
class StringWaiter
{
    private $promise;
    public function __construct(PromiseInterface $promise)
    {
        $this->promise = $promise;
    }
    public function __toString()
    {
        try {
            return $this->promise->wait();
        } catch (Exception $e) {
            return "Error: " . $e->getMessage() . "\n";
        }
    }
}
$usernameApiPromise = $usernameClient->postAsync('generate-username');
$usernamePromise = new Promise(function () use($usernameApiPromise, &$usernamePromise) {
    $data = json_decode($usernameApiPromise->wait()->getBody());
    $usernamePromise->resolve($data->username);
});
$username = new StringWaiter($usernamePromise);
echo "Username: {$username}\n";
// there is a bit of ugliness in making each call, but you shoudl be able to hide it behind some
// helper functions.  There is lots of power in the guzzle promises implmentation, but I find it
// to be a little clunky in use.  You will want to develop wrappers that give you the patterns
// you want.
// To finish up lets visit 5-async-timing.php and see how much time we are really saving
Пример #22
0
 public function testUsesYieldedKeyInFulfilledCallback()
 {
     $r1 = new Promise(function () use(&$r1) {
         $r1->resolve(new Response());
     });
     $r2 = new Promise(function () use(&$r2) {
         $r2->resolve(new Response());
     });
     $r3 = new Promise(function () use(&$r3) {
         $r3->resolve(new Response());
     });
     $handler = new MockHandler([$r1, $r2, $r3]);
     $c = new Client(['handler' => $handler]);
     $keys = [];
     $requests = ['request_1' => new Request('GET', 'http://example.com'), 'request_2' => new Request('GET', 'http://example.com'), 'request_3' => new Request('GET', 'http://example.com')];
     $p = new Pool($c, $requests, ['pool_size' => 2, 'fulfilled' => function ($res, $index) use(&$keys) {
         $keys[] = $index;
     }]);
     $p->promise()->wait();
     $this->assertCount(3, $keys);
     $this->assertSame($keys, array_keys($requests));
 }
 /**
  * @param Promise $promise
  */
 protected function wait(Promise $promise)
 {
     $promise->wait();
 }
Пример #24
0
 /**
  * Magic method which intercepts async calls, finds the sequential version, and wraps it in a
  * {@see Promise} object. In order for this to happen, the called methods need to be in the
  * following format: `createAsync`, where `create` is the sequential method being wrapped.
  *
  * @param $methodName The name of the method being invoked.
  * @param $args       The arguments to be passed to the sequential method.
  *
  * @return Promise
  */
 public function __call($methodName, $args)
 {
     if (substr($methodName, -5) === 'Async') {
         $realMethod = substr($methodName, 0, -5);
         if (!method_exists($this, $realMethod)) {
             throw new \InvalidArgumentException(sprintf('%s is not a defined method on %s', $realMethod, get_class($this)));
         }
         $promise = new Promise(function () use(&$promise, $realMethod, $args) {
             $value = call_user_func_array([$this, $realMethod], $args);
             $promise->resolve($value);
         }, function ($e) use(&$promise) {
             $promise->reject($e);
         });
         return $promise;
     }
 }
 /**
  * @param RequestInterface $request
  * @param array $options
  * @return Promise
  */
 public function __invoke(RequestInterface $request, array $options)
 {
     $ready = false;
     $promise = new Promise(function () use(&$ready) {
         do {
             $this->loop->tick();
         } while (!$ready);
     });
     $this->requestFactory->create($request, $options, $this->httpClient, $this->loop)->then(function (ResponseInterface $response) use(&$ready, $promise) {
         $ready = true;
         $promise->resolve($response);
         $this->invokeQueue();
     }, function ($error) use(&$ready, $promise) {
         $ready = true;
         $promise->reject($error);
         $this->invokeQueue();
     });
     return $promise;
 }