[Aio] Gracefully handle RPCs ends pre-maturely (#25884)

* Gracefully handle RPCs ends pre-maturely

* Fix a typo
pull/25885/head
Lidi Zheng 4 years ago committed by GitHub
parent 04166bd7d2
commit 09f17db9ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 27
      src/python/grpcio/grpc/_cython/_cygrpc/aio/call.pyx.pxi

@ -134,37 +134,38 @@ cdef class _AioCall(GrpcCallWrapper):
cdef void _set_status(self, AioRpcStatus status) except *: cdef void _set_status(self, AioRpcStatus status) except *:
cdef list waiters cdef list waiters
# No more waiters should be expected since status has been set.
self._status = status self._status = status
if self._initial_metadata is None: if self._initial_metadata is None:
self._set_initial_metadata(_IMMUTABLE_EMPTY_METADATA) self._set_initial_metadata(_IMMUTABLE_EMPTY_METADATA)
# No more waiters should be expected since status for waiter in self._waiters_status:
# has been set.
waiters = self._waiters_status
self._waiters_status = None
for waiter in waiters:
if not waiter.done(): if not waiter.done():
waiter.set_result(None) waiter.set_result(None)
self._waiters_status = []
for callback in self._done_callbacks: for callback in self._done_callbacks:
callback() callback()
cdef void _set_initial_metadata(self, tuple initial_metadata) except *: cdef void _set_initial_metadata(self, tuple initial_metadata) except *:
if self._initial_metadata is not None:
# Some gRPC calls might end before the initial metadata arrived in
# the Call object. That causes this method to be invoked twice: 1.
# filled with an empty metadata; 2. updated with the actual user
# provided metadata.
return
cdef list waiters cdef list waiters
# No more waiters should be expected since initial metadata has been
# set.
self._initial_metadata = initial_metadata self._initial_metadata = initial_metadata
# No more waiters should be expected since initial metadata for waiter in self._waiters_initial_metadata:
# has been set.
waiters = self._waiters_initial_metadata
self._waiters_initial_metadata = None
for waiter in waiters:
if not waiter.done(): if not waiter.done():
waiter.set_result(None) waiter.set_result(None)
self._waiters_initial_metadata = []
def add_done_callback(self, callback): def add_done_callback(self, callback):
if self.done(): if self.done():

Loading…
Cancel
Save