Search code examples
grpcgrpc-c#grpc-c++

gRPC wait server ready


I'm writing test (with gtest) with grpc similar to the following (in C++ pseudocode):

class Fixture {
  void SetUp() { m_server = BuildAndStart(); }
  void TearDown() { m_server->Shutdown(); }
};

TEST_F(Fixture, Test1) { ASSERT_EQ(clientStub->rpcCall(ctx), grpc::Status::OK); }
TEST_F(Fixture, Test2) { ASSERT_EQ(clientStub->rpcCall(ctx), grpc::Status::OK); }

When compiling (clang++11) with a thread sanitizer (grpc library compiling with tsan too) sometimes I get an error UNAVALABLE (code 14) with logs: "Failed to pick subchannel", "Failed to connect to all addresses" and observe the state of the channel is TRANSIENT_FAILURE.

But only the first test always fails (Test1). Searching the internet I found the following suitable solution

In other words, with tsan I guess grpc library does not have enough time to fully initialize (Test2 is always OK). After use grpc::ClientContext::set_wait_for_ready(bool) method problem solved

TEST_F(Fixture, Test1) { ASSERT_EQ(clientStub->rpcCall(ctxWithWait), grpc::Status::OK); }
TEST_F(Fixture, Test2) { ASSERT_EQ(clientStub->rpcCall(ctxWithWait), grpc::Status::OK); }

My questions are:

  1. grpc::ClientContext::set_wait_for_ready(bool) marked as EXPERIMENTAL (C++ api) and may be removed in the future, but grpc::ClientContext::set_fail_fast(bool) method is DEPRECATED. It's recommended to use wait_for_ready(). Is it true that in the future set_wait_for_ready should become a replacement set_fail_fast?
  2. Are there any other ways to solve this problem? I was also looking at ChannelState API method bool grpc::ChannelInterface::WaitForConnected(T deadline). Which way is more correct and reliable?

I will also need to implement similar logic in C# code. In C# this is a CallOptions.WithWaitForReady(bool) method, but it's EXPERIMENTAL too

Wished to clear up a misunderstanding and choose the right solution.


Solution

    1. grpc::ClientContext::set_wait_for_ready(bool) became a regular API so you don't worry about EXPERIMENTAL mark anymore.

    2. Using WaitForConnected also works. Both can be the right solution for this case because it's in the unit test and it's unlikely to see the server restart during the test.