Tushar Jagtap
Tushar Jagtap

Reputation: 55

Retry Policies are not getting forwarded to google client

I'm using google-cloud-cpp SDK from here and I'm trying to test for an incorrect endpoint scenario where I'm expecting an error within 100 milliseconds as per the policy I setup when I pass in an incorrect endpoint url. However, my test hangs for a long time instead. For this particular case, I need to override the policies of an existing gcs::Client for ListObjects case only and want to re-use the client that I have already created. I wrote a small program that simulates behavior of my actual issue in the codebase. I'm not sure why the retry policy for LimitedTimeRetryPolicy is not getting forwarded to the new client I created? Appreciate any help and/or examples.

using namespace google::cloud::storage;
using ::google::cloud::StatusOr;
// Ex: ./wrongEndpoint
int main(int argc, char* argv[]) {
    auto options = ClientOptions::CreateDefaultClientOptions();
    options.value().set_enable_http_tracing(true);
    options.value().set_enable_raw_client_tracing(true);
    options.value().set_endpoint("https://somegarbage.com");
    options.value().set_download_stall_timeout(std::chrono::seconds(1));

    // Original Client in the codebase
    Client clientX(*options);

    // Creating new client for ListObjects from the raw_client with a retry policy
    std::shared_ptr<internal::RawClient> Rclient = clientX.raw_client();
    Client client = Client(Rclient, LimitedTimeRetryPolicy(std::chrono::milliseconds(100)));
    try{
        for (auto&& object_metadata : client.ListObjects("march30")) {
            if (!object_metadata) {
                throw std::runtime_error(object_metadata.status().message());
            }

            std::cout << "bucket_name=" << object_metadata->bucket()
                << ", object_name=" << object_metadata->name() << "\n";
        }
    } catch(std::exception &ex) {
        std::cout << ex.what() << "\n";
    }
}

Upvotes: 0

Views: 176

Answers (1)

coryan
coryan

Reputation: 826

To understand why this does not work I need to talk about the implementation internals, sorry.

In your code clientX contains a stack of RawClient objects, more or less as follows: clientX -> LoggingClient -> RetryClient(DefaultRetryPolicy) -> CurlClient. Each element in that list is a decorator, it performs a function (say logging) and delegates the work to the next element.

When you create client in your code it contains a new stack client -> RetryClient(LimitedTimeRetryPolicy(100ms)) -> LoggingClient -> RetryClient(DefaultRetryPolicy) -> CurlClient.

That means every request is now subject to the original retry policy and to your new retry policy, the new retry policy is much shorter than the original one, so (most likely) it just fails immediately.

Rebuilding the stack of internal::RawClient objects is not something we ever thought about. I can describe how to do it, but I will note that you would be using classes in the google::cloud::internal:: namespace, which may change at any time without notice.

Basically you would need to use RTTI to discover the type of each element in this stack, depending on the type they have a client() member function that gives you the next element. Once you discover the right one to replace, you would create it, preserving all the downstream elements in the stack. Then you would recreate a Client using the NoDecorations constructor.

Upvotes: 0

Related Questions