Hi,
Need some help figuring out if this is a bug in gRPC or improper code.
Thanks!
I have this scenario between Python and C#:
- A python server with a streaming rpc
- A c# client that constantly queries that streaming rpc
- Problem: if the server goes down while the client was asking (not sure exactly timing), recreating the channel in the client won't work for a new server
- The client will continue to create Idle channels that will timeout on deadline exceeded
- Output and simplified code below
Normally it works fine, but if I terminate the server manually (ctrl+c) while the client was in the streaming call,
spawning a new server and recreating the channel in the client won't work. I believe whether I let the client wait
for the deadline with the server down or not has no effect on being able to reconnect later.
Calls to call.Dispose() or channel.ShutdownAsync() seem to have no effect. Adding some grace to server.stop() seemed to have no effect either.
When re-connection works, the channel state is TransientFailure during the server downtime. If somehow the channel reaches 'Idle' state during server downtime, it will no longer connect.
// client loop after failure..
[error] Status(StatusCode=DeadlineExceeded, Detail="Deadline Exceeded")
[info] CHANNEL STATE 'Idle'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CODE
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Server.py
# streaming response
def GetItemUpdates(self, request, context):
for item in my_db.items():
...
yield response
# server listening
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
server.start()
try
...
# interrupted by ctrl+C
except KeyboardInterrupt:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Client.cs
// called from a thread periodically
private async Task RefreshStudyStatusFromController()
{
Channel channel = new Channel("localhost:myport", ChannelCredentials.Insecure);
var controller = new P.PClient(channel);
try {
// call the streaming rpc
call = controller.GetItemUpdates(input, deadline: deadline);
while (await call.ResponseStream.MoveNext())
{ ... }
}
catch (RpcException rpcEx) { ...
call.Dispose();
await channel.ShutdownAsync();
}
}