2

I am sending multiple async promises with a guzzle timeout set to 30, I am wondering how to capture if any promises timed out so that I can report on this error. Please see the code below. Essentially I want to use any responses I can before timeout and capture those that do timeout.

foreach ($apiRequests as $guzzleParameters) {
    $request = new Request($guzzleParameters->getType(), $guzzleParameters->getApiEndpoint(), $guzzleParameters->getHeaders(), $guzzleParameters->getBody());
    $promises[$guzzleParameters->createKey()] = $this->client->sendAsync($request)->then(
                function (ResponseInterface $res) {
                    return $res;
                },
                function (RequestException $e) {
                    switch ($e->getCode()) {
                        case 400:
                        // log error 
                            break;
                        case 401:
                        // log error 
                            break;
                        case 403:
                        // log error 
                            break;
                        case 404:
                        // log error 
                            break;
                    }
                    return $e->getResponse();
                }
            );
        }
$responses = Promise\Utils::settle($promises)->wait(true);
bhucho
  • 3,903
  • 3
  • 16
  • 34
pilotman
  • 624
  • 1
  • 6
  • 23
  • try to get exception response only when you have one, you are using requestException so if it will have response then only you can get code will break in case of status 503 or any other 50X status, see [Handling exceptions on a Pool of Requests](https://stackoverflow.com/questions/56183592/handling-exceptions-on-a-pool-of-requests) – bhucho Mar 25 '21 at 01:55
  • also how are you checking timeout I can't see it in above code, you are saying you have set guzzle timeout to 30, it is for each request or for the pool of request, also show whats in `$guzzleParameters->getHeaders()` – bhucho Mar 25 '21 at 01:59
  • Hi so the time out is set as so: $client = new Client([ 'timeout' => 30 ]); in, headers is empty and body is empty, (this is a reusable component but for my case the headers and body is not needed. Just the api and the prefix. The 30 is for the pool. I am unsure in how to detect if any promises time out and how to test this – pilotman Mar 25 '21 at 09:32
  • use [on_stats](https://docs.guzzlephp.org/en/stable/request-options.html#on-stats) request option when sending a request and log all the data or use getTransferTime() provided by onstats instance, should I share an example? – bhucho Mar 25 '21 at 12:03
  • An example would be great thanks – pilotman Mar 25 '21 at 15:59

1 Answers1

2

As I have understood you want to record time of each request in async and then you can add it up and put a flag that when summation reaches more than 30.

NOTE: Non tested code but the on_stats portion code is tested

foreach ($apiRequests as $key => $guzzleParameters) {
    $LogStats = [];
    $request = new Request($guzzleParameters->getType(), $guzzleParameters->getApiEndpoint(), $guzzleParameters->getHeaders(), $guzzleParameters->getBody());
    $promises[$guzzleParameters->createKey()] = $this->client->sendAsync($request, [
                    'on_stats' => function (\GuzzleHttp\TransferStats $stats) {
                        // $LogStats["uri"] = $stats->getEffectiveUri();
                        $LogStats[$key]["time"] = $stats->getTransferTime();
                        // $LogStats["stats"] = json_encode($stats->getHandlerStats());
                        // Log::debug("\n--------------------------------\nDebug Solr Request Stats :: ", $LogStats);
                    }
                ])->then(
                function (ResponseInterface $res) {
                    return $res;
                },
                function (RequestException $e) {
                     // ....
                    }
                    return $e->getResponse();
                }
            );
        }
$responses = Promise\Utils::settle($promises)->wait(true);

Here I have used on_stats, you can put a count on all the time and then sum it up and once it reaches 30 set flag as true. then you can know after which key the request failed.

bhucho
  • 3,903
  • 3
  • 16
  • 34
  • you can set to a variable $debug as true in the method to run on_stats in debug mode only, also this is just one idea to help solve your problem case – bhucho Mar 26 '21 at 05:05