google-cloud-php icon indicating copy to clipboard operation
google-cloud-php copied to clipboard

Request is not retried on timeout using `requestTimeout` and `retries`

Open bernardwiesner opened this issue 3 years ago • 2 comments

Environment details

  • OS: alpine linux 3.14
  • PHP version: 8.1
  • Package name and version: google/cloud-pubsub v1.35

Overview

Requests are not retried if the requestTimeout is reached. I checked the source code and found inside the RetryDeciderTrait.php only these http codes are retried:

private $httpRetryCodes = [
    500,
    502,
    503
];

There seems to be no way to override this, I also need to retry when the timeout is reached.

Steps to reproduce

Run below snipped with a slow internet connection, request times out after 1 second and is not retried.

Code example

return new PubSubClient([
    'retries' => 3,
    'requestTimeout' => 1
]);

bernardwiesner avatar Apr 20 '22 23:04 bernardwiesner

Hi @dwsupplee

Thanks for investigating this issue. Is there some workaround for this currently? Thanks

bernardwiesner avatar May 02 '22 02:05 bernardwiesner

You can set which http status codes to retry by calling setHttpRetryCodes.

https://github.com/googleapis/google-cloud-php/blob/3095675fc315bc75ba1daf7b1dc805c233fb083a/Core/src/RetryDeciderTrait.php#L101

If PubSubClient works anything like Google Cloud Storage's StorageClient class, you would need to use your own class that uses this trait, set your desired http codes and call and pass the trait's getRetryFunction() return value into your PubSubClient's constructor config array under the key "restRetryFunction"

Related to retrying, what I'm curious about though is how to retry curl errors, because I've been seeing a lot of curl 18 errors when reading files from Google Cloud Storage.

georaldc avatar May 26 '22 02:05 georaldc

Hi @bernardwiesner Thanks for filling the issue.

Apologies for the delay in response.

One way to think about could be to take control of how you want to retry instead of just overriding the error codes. In this case, you could use the configuration option restRetryFunction that decides whether an operation should be retried or not.

So, something like this could be customised as per your need:

$client = new PubSubClient([
    'retries' => 3,
    'requestTimeout' => 1,
    'restRetryFunction' => function ($ex, $attempt) {
        // $ex is the exception object
        // $attempt is the retry attempt
        $statusCode = $ex->getCode();

        $httpRetryCodes = []; // your list of retry codes

        if (in_array($statusCode, $httpRetryCodes)) {
            return true;
        }

        return false;
    }
]);

You could even check for the type of exception etc.

Hope this helps your use case.

saranshdhingra avatar Mar 23 '23 21:03 saranshdhingra