Question first, context below. How can I perform some server-side action (eg, cleanup) based on a cancellation of an RPC from the client with an async gRPC python server?
In my microservice, I have an asyncio
gRPC server whose main RPCs are bidirectional streams.
On the client side (which is also using asyncio), when I cancel something, it raises an asyncio.CancelledError
which is caught and not reraised by the grpc
core:
except asyncio.CancelledError:
_LOGGER.debug('RPC cancelled for servicer method [%s]', _decode(rpc_state.method()))
So I cannot rely on catching the asyncio.CancelledError
in my own code, because it's caught beforehand and not reraised.
The shared context is supposed to contain information as to whether the RPC was canceled on the client side, by calling .cancel()
from the RPC call and being able to see if it was canceled by calling .cancelled()
:
https://grpc.github.io/grpc/python/grpc_asyncio.html#shared-context
abstract cancel()
Cancels the RPC. Idempotent and has no effect if the RPC has already terminated. Returns A bool indicates if the cancellation is performed or not. Return type bool
abstract cancelled()
Return True if the RPC is cancelled. The RPC is cancelled when the cancellation was requested with cancel(). Returns A bool indicates whether the RPC is cancelled or not. Return type bool
However, this shared context is not attached to the context
variable given to the RPC on the server side by the gRPC generated code. (I cannot run context.cancelled()
or context.add_done_callback
; they're not present)
So, again, the question: How can I perform some server-side action (eg, cleanup) based on a cancellation of an RPC from the client with an async gRPC python server?