예제 #1
4
 public function index()
 {
     $promises = call_user_func(function () {
         foreach ($this->usernames as $username) {
             (yield $this->client->requestAsync('GET', 'https://api.github.com/users/' . $username));
         }
     });
     // Wait till all the requests are finished.
     \GuzzleHttp\Promise\all($promises)->then(function (array $responses) {
         $this->profiles = array_map(function ($response) {
             return json_decode($response->getBody(), true);
         }, $responses);
     })->wait();
     // Return JSON response
     $response = new Response();
     // StreamInterface objects are not immutable!
     $response->getBody()->write($this->html());
     return $response->withHeader('Content-type', 'text/html');
 }
예제 #2
0
 /**
  * @return static
  */
 public function index()
 {
     $promises = array_map(function ($username) {
         $url = 'https://api.github.com/users/' . $username;
         return $this->client->sendAsync(new Request('GET', $url));
         // return $this->client->requestAsync('GET', $url);
     }, $this->usernames);
     // Wait till all the requests are finished.
     \GuzzleHttp\Promise\all($promises)->then(function (array $responses) {
         $this->profiles = array_map(function ($response) {
             return json_decode($response->getBody(), true);
         }, $responses);
     })->wait();
     // Return JSON response
     $response = new \Zend\Diactoros\Response();
     // StreamInterface objects are not immutable!
     $response->getBody()->write(json_encode($this->profiles));
     return $response->withHeader('Content-Type', 'application/json');
 }
예제 #3
0
 public function testAllThrowsWhenAnyRejected()
 {
     $a = new Promise();
     $b = new Promise();
     $c = new Promise();
     $d = \GuzzleHttp\Promise\all([$a, $b, $c]);
     $b->resolve('b');
     $a->reject('fail');
     $c->resolve('c');
     $d->then(function ($value) use(&$result) {
         $result = $value;
     }, function ($reason) use(&$result) {
         $result = $reason;
     });
     P\queue()->run();
     $this->assertEquals('fail', $result);
 }
예제 #4
0
 public static function destroyAsync($ids)
 {
     // We'll initialize a count here so we will return the total number of deletes
     // for the operation. The developers can then check this number as a boolean
     // type value or get this total count of records deleted for logging, etc.
     $ids = is_array($ids) ? $ids : func_get_args();
     // We will actually pull the models from the database table and call delete on
     // each of them individually so that their events get fired properly with a
     // correct set of attributes in case the developers wants to check these.
     $tasks = [];
     foreach ($ids as $id) {
         if ($model = static::find($id)) {
             $tasks[] = $model->deleteAsync($id);
         }
     }
     return \GuzzleHttp\Promise\all($tasks)->then(function ($results) {
         $count = 0;
         foreach ($results as $result) {
             if ($result) {
                 $count++;
             }
         }
         return $count;
     });
 }
예제 #5
0
 public function onKernelController(FilterControllerEvent $event)
 {
     if (!$event->isMasterRequest()) {
         return;
     }
     $request = $event->getRequest();
     if (!$request->attributes->has('_api')) {
         return;
     }
     /** @var Api $api */
     $api = $request->attributes->get('_api');
     $subRequests = $this->getSubRequests($request);
     $bulk = $api->isBulkable() && $subRequests;
     $stream = ($api->isStreamable() || $bulk) && $this->shouldStream($request);
     if (!$bulk && !$stream) {
         $request->attributes->set('stream', $this->noop);
         return;
     }
     // This listener will unwind/spread the calls, so don't trigger other Api listeners.
     $request->attributes->remove('_api');
     if ($stream) {
         $headers = ['content-type' => 'application/json; boundary=NL', 'x-accel-buffering' => 'no'];
     } else {
         $headers = ['content-type' => 'application/json'];
     }
     if ($subRequests) {
         $event->setController(function () use($request, $headers, $subRequests, $stream) {
             return new StreamedResponse(function () use($request, $subRequests, $stream) {
                 $promises = [];
                 foreach ($subRequests as $i => $requestParams) {
                     // Forward the query string without the 'payload', and put all the parameters in the body.
                     $query = $request->query->all();
                     if (isset($query['payload'])) {
                         unset($query['payload']);
                     }
                     $subRequest = $request->duplicate([], $requestParams);
                     // Also force-make it a POST request, so it can contain a body.
                     $subRequest->setMethod('POST');
                     $subRequest->attributes->set('stream', $stream ? $this->createStreamer($i) : $this->noop);
                     /* @var PromiseInterface $promise */
                     $promises[] = $promise = $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true, false);
                     if ($stream) {
                         $streamer = $this->createStreamer($i);
                         $promise->then(function (Response $response) use($streamer) {
                             $streamer($response->getContent(), true);
                         });
                     }
                 }
                 $responses = \GuzzleHttp\Promise\all($promises)->wait();
                 if (!$stream) {
                     echo '[';
                     for (reset($responses); $response = current($responses); next($responses)) {
                         echo $response->getContent();
                         if (current($responses)) {
                             echo ',';
                         }
                     }
                     echo ']';
                 }
             }, 200, $headers);
         });
     } else {
         $event->setController(function () use($request, $headers) {
             return new StreamedResponse(function () use($request) {
                 $request->attributes->set('stream', $this->createStreamer());
                 // We duplicate the request because the profiler component's token keeps a reference to the parent request's token,
                 // creating an infinite loop when attempting to display profiler info.
                 $response = $this->httpKernel->handle($request->duplicate(), HttpKernelInterface::SUB_REQUEST, true, true);
                 // The streamer outputs a new line as the ending delimiter. In single action calls, the ending line should be
                 // the actual response without a new line at the end. That's why streaming single calls have a resulting
                 // response, but bulk calls don't have one.
                 echo $response->getContent();
             }, 200, $headers);
         });
     }
 }
예제 #6
0
 /**
  * Creates a Dynamic Large Object by chunking a file into smaller segments and uploading them into a holding
  * container. When this completes, a manifest file is uploaded which references the prefix of the segments,
  * allowing concatenation when a request is executed against the manifest.
  *
  * @param array  $data                     {@see \OpenStack\ObjectStore\v1\Api::putObject}
  * @param int    $data['segmentSize']      The size in Bytes of each segment
  * @param string $data['segmentContainer'] The container to which each segment will be uploaded
  * @param string $data['segmentPrefix']    The prefix that will come before each segment. If omitted, a default
  *                                         is used: name/timestamp/filesize
  *
  * @return Object
  */
 public function createLargeObject(array $data)
 {
     /** @var \Psr\Http\Message\StreamInterface $stream */
     $stream = $data['stream'];
     $segmentSize = isset($data['segmentSize']) ? $data['segmentSize'] : 1073741824;
     $segmentContainer = isset($data['segmentContainer']) ? $data['segmentContainer'] : $this->name . '_segments';
     $segmentPrefix = isset($data['segmentPrefix']) ? $data['segmentPrefix'] : sprintf("%s/%s/%d", $data['name'], microtime(true), $stream->getSize());
     /** @var \OpenStack\ObjectStore\v1\Service $service */
     $service = $this->getService();
     if (!$service->containerExists($segmentContainer)) {
         $service->createContainer(['name' => $segmentContainer]);
     }
     $promises = [];
     $count = 0;
     while (!$stream->eof() && $count < round($stream->getSize() / $segmentSize)) {
         $promises[] = $this->model(Object::class)->createAsync(['name' => sprintf("%s/%d", $segmentPrefix, ++$count), 'stream' => new LimitStream($stream, $segmentSize, ($count - 1) * $segmentSize), 'containerName' => $segmentContainer]);
     }
     /** @var Promise $p */
     $p = \GuzzleHttp\Promise\all($promises);
     $p->wait();
     return $this->createObject(['name' => $data['name'], 'objectManifest' => sprintf("%s/%s", $segmentContainer, $segmentPrefix)]);
 }
예제 #7
0
 /**
  * @dataProvider requestList
  */
 public function testQueueLimitsNumberOfProcessingRequests(array $queueData, $expectedDuration, $throttleLimit, $threshold = 0.05)
 {
     $handler = new HandlerStack(new LoopHandler());
     $handler->push(ThrottleMiddleware::create());
     $client = new \GuzzleHttp\Client(['handler' => $handler, 'base_uri' => Server::$url, 'timeout' => 10]);
     $queueEnd = $promises = $responses = $expectedStart = [];
     Server::start();
     Server::enqueue(array_fill(0, count($queueData), new Response()));
     foreach ($queueData as $queueItem) {
         list($queueId, $requestDuration, $expectedStartTime) = $queueItem;
         $options = [RequestOptions::HTTP_ERRORS => false, RequestOptions::HEADERS => ['duration' => $requestDuration], 'throttle_id' => $queueId, 'throttle_limit' => $throttleLimit];
         $expectedStart[$queueId] = $expectedStartTime;
         $promises[] = $client->getAsync('', $options)->then(function () use($queueId, &$queueStart, &$queueEnd) {
             if (!isset($queueStart[$queueId])) {
                 $queueStart[$queueId] = microtime(true);
             }
             $queueEnd[$queueId] = microtime(true);
         });
     }
     $start = microtime(true);
     $GLOBALS['s'] = microtime(1);
     \GuzzleHttp\Promise\all($promises)->wait();
     $duration = microtime(true) - $start;
     $this->assertGreaterThan($expectedDuration - $threshold, $duration);
     $this->assertLessThan($expectedDuration + $threshold, $duration);
     foreach ($queueEnd as $i => $endedAt) {
         $duration = $endedAt - $start;
         //            $this->assertGreaterThan($expectedDuration - $threshold, $endedAt - $start, "Queue #$i started too soon");
         //            $this->assertLessThan($queueInfo->getExpectedDuration() + $threshold, $queueInfo->getDuration(), "Queue #$i started too late");
         //
         //            $this->assertGreaterThan($started + $queueInfo->getExpectedDelay() - $threshold, $queueInfo->getStartedAt(), "Queue #$i popped too early");
         //            $this->assertLessThan($started + $queueInfo->getExpectedDelay() + $threshold, $queueInfo->getStartedAt(), "Queue #$i popped too late");
     }
 }