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:
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
?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.
grpc::ClientContext::set_wait_for_ready(bool)
became a regular API so you don't worry about EXPERIMENTAL
mark anymore.
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.