I'm having an issue with client disconnection using a Python gRPC server with a unary-stream procedure. I may have missed something in the documentation, but multiple attempts of checking whether or not the client is still active have all failed.
My hope is to find a way for the Servicer to detect when to stop generating values when a client disconnects. A client subscribes to a stream of updates once and receives all changes to the server state for an unbounded amount of time. The actual server implementation should also send values regularly on a heartbeat with low activity. A minimal example is given below that demonstrates my problem.
class TaskService(proto_grpc.TaskServiceServicer):
def Subscribe(self, request, context):
print 'subscribed'
while True:
time.sleep(1)
print 'sending'
yield proto.TaskState(state='IDLE')
print 'finished'
def main():
server = grpc.server(concurrent.futures.ThreadPoolExecutor(max_workers=3))
proto_grpc.add_TaskServiceServicer_to_server(
TaskService(),
server,
)
server.start()
try:
while True:
time.sleep(1)
print 'bump'
finally:
print 'stopping'
server.stop(grace=0)
print 'stopped'
There are two issues at play here. First, if a client subscribes and then is disconnected forcefully, the server will continue to send updates to that channel. This means if three clients have ever subscribed to this server, then a fourth may never connect in the future (due to the low number in the thread pool). This seems wrong, but I may be missing a setting somewhere.
Second, if a client subscribes and then disconnects, the server will never shut down completely. The process will hang in an un-killable state. This does not occur when a client never connects, or if a client connects but stays connected as the process shuts down.
The following output occurs when the server is killed after a client connects:
subscribed
bump
sending
bump
sending
^C
stopping
stopped
Traceback (most recent call last):
...
time.sleep(1)
KeyboardInterrupt
sending
<process terminated gracefully>
The following output occurs when the server is killed after a client disconnects:
subscribed
bump
sending
bump
<client is killed>
sending
bump
^C
stopping
stopped
Traceback (most recent call last):
...
time.sleep(1)
KeyboardInterrupt
sending
<process hangs indefinitely>
I hope there is an easy solution as I simply misunderstood the correct use to implement a streaming response and apologize in advance if there is.