def _handle_event(event, state, response_deserializer): callbacks = [] for batch_operation in event.batch_operations: operation_type = batch_operation.type() state.due.remove(operation_type) if operation_type == cygrpc.OperationType.receive_initial_metadata: state.initial_metadata = batch_operation.initial_metadata() elif operation_type == cygrpc.OperationType.receive_message: serialized_response = batch_operation.message() if serialized_response is not None: response = _common.deserialize(serialized_response, response_deserializer) if response is None: details = 'Exception deserializing response!' _abort(state, grpc.StatusCode.INTERNAL, details) else: state.response = response elif operation_type == cygrpc.OperationType.receive_status_on_client: state.trailing_metadata = batch_operation.trailing_metadata() if state.code is None: code = _common.CYGRPC_STATUS_CODE_TO_STATUS_CODE.get( batch_operation.code()) if code is None: state.code = grpc.StatusCode.UNKNOWN state.details = _unknown_code_details( code, batch_operation.details()) else: state.code = code state.details = batch_operation.details() state.debug_error_string = batch_operation.error_string() callbacks.extend(state.callbacks) state.callbacks = None return callbacks
async def __call__(self, request, timeout=None, metadata=None, credentials=None, wait_for_ready=None, compression=None): if timeout: raise NotImplementedError("TODO: timeout not implemented yet") if metadata: raise NotImplementedError("TODO: metadata not implemented yet") if credentials: raise NotImplementedError("TODO: credentials not implemented yet") if wait_for_ready: raise NotImplementedError( "TODO: wait_for_ready not implemented yet") if compression: raise NotImplementedError("TODO: compression not implemented yet") response = await self._channel.unary_unary( self._method, _common.serialize(request, self._request_serializer)) return _common.deserialize(response, self._response_deserializer)
async def _conduct_rpc(self) -> ResponseType: try: serialized_response = await self._cython_call.stream_unary( self._metadata, self._metadata_sent_observer) except asyncio.CancelledError: if not self.cancelled(): self.cancel() if self._cython_call.is_ok(): return _common.deserialize(serialized_response, self._response_deserializer) else: return cygrpc.EOF
async def _conduct_rpc(self) -> ResponseType: try: serialized_response = await self._cython_call.stream_unary( self._metadata, self._metadata_sent_observer) except asyncio.CancelledError: if not self.cancelled(): self.cancel() # Raises RpcError if the RPC failed or cancelled await self._raise_for_status() return _common.deserialize(serialized_response, self._response_deserializer)
async def _process(self) -> ResponseType: await self._call async for serialized_response in self._bytes_aiter: if self._cancellation.done(): await self._status if self._status.done(): # Raises pre-maturely if final status received here. Generates # more helpful stack trace for end users. await self._raise_rpc_error_if_not_ok() yield _common.deserialize(serialized_response, self._response_deserializer) await self._raise_rpc_error_if_not_ok()
async def __call__(self, request, timeout=None, metadata=None, credentials=None, wait_for_ready=None, compression=None): """Asynchronously invokes the underlying RPC. Args: request: The request value for the RPC. timeout: An optional duration of time in seconds to allow for the RPC. metadata: Optional :term:`metadata` to be transmitted to the service-side of the RPC. credentials: An optional CallCredentials for the RPC. Only valid for secure Channel. wait_for_ready: This is an EXPERIMENTAL argument. An optional flag to enable wait for ready mechanism compression: An element of grpc.compression, e.g. grpc.compression.Gzip. This is an EXPERIMENTAL option. Returns: The response value for the RPC. Raises: RpcError: Indicating that the RPC terminated with non-OK status. The raised RpcError will also be a Call for the RPC affording the RPC's metadata, status code, and details. """ if timeout: raise NotImplementedError("TODO: timeout not implemented yet") if metadata: raise NotImplementedError("TODO: metadata not implemented yet") if credentials: raise NotImplementedError("TODO: credentials not implemented yet") if wait_for_ready: raise NotImplementedError( "TODO: wait_for_ready not implemented yet") if compression: raise NotImplementedError("TODO: compression not implemented yet") response = await self._channel.unary_unary( self._method, _common.serialize(request, self._request_serializer)) return _common.deserialize(response, self._response_deserializer)
async def _read(self) -> ResponseType: # Wait for the request being sent await self._preparation # Reads response message from Core try: raw_response = await self._cython_call.receive_serialized_message() except asyncio.CancelledError: if not self.cancelled(): self.cancel() await self._raise_for_status() if raw_response is cygrpc.EOF: return cygrpc.EOF else: return _common.deserialize(raw_response, self._response_deserializer)
async def _read(self) -> ResponseType: # Wait for the request being sent await self._send_unary_request_task # Reads response message from Core try: raw_response = await self._cython_call.receive_serialized_message() except asyncio.CancelledError: if self._code != grpc.StatusCode.CANCELLED: self.cancel() raise if raw_response is None: return None else: return _common.deserialize(raw_response, self._response_deserializer)
def receive_message(receive_message_event): serialized_request = _serialized_request(receive_message_event) if serialized_request is None: with state.condition: if state.client is _OPEN: state.client = _CLOSED state.condition.notify_all() return _possibly_finish_call(state, _RECEIVE_MESSAGE_TOKEN) else: request = _common.deserialize(serialized_request, request_deserializer) with state.condition: if request is None: _abort( state, call, cygrpc.StatusCode.internal, b'Exception deserializing request!') else: state.request = request state.condition.notify_all() return _possibly_finish_call(state, _RECEIVE_MESSAGE_TOKEN)
def receive_message(receive_message_event): serialized_request = _serialized_request(receive_message_event) if serialized_request is None: with state.condition: if state.client is _OPEN: state.client = _CLOSED state.condition.notify_all() return _possibly_finish_call(state, _RECEIVE_MESSAGE_TOKEN) else: request = _common.deserialize(serialized_request, request_deserializer) with state.condition: if request is None: _abort(state, call, cygrpc.StatusCode.internal, b'Exception deserializing request!') else: state.request = request state.condition.notify_all() return _possibly_finish_call(state, _RECEIVE_MESSAGE_TOKEN)
async def _invoke(self) -> ResponseType: serialized_request = _common.serialize(self._request, self._request_serializer) # NOTE(lidiz) asyncio.CancelledError is not a good transport for status, # because the asyncio.Task class do not cache the exception object. # https://github.com/python/cpython/blob/edad4d89e357c92f70c0324b937845d652b20afd/Lib/asyncio/tasks.py#L785 try: serialized_response = await self._cython_call.unary_unary( serialized_request, self._metadata) except asyncio.CancelledError: if not self.cancelled(): self.cancel() if self._cython_call.is_ok(): return _common.deserialize(serialized_response, self._response_deserializer) else: return cygrpc.EOF
def __await__(self): """Wait till the ongoing RPC request finishes. Returns: Response of the RPC call. Raises: AioRpcError: Indicating that the RPC terminated with non-OK status. asyncio.CancelledError: Indicating that the RPC was canceled. """ # We can not relay on the `done()` method since some exceptions # might be pending to be catched, like `asyncio.CancelledError`. if self._response: return self._response elif self._exception: raise self._exception try: buffer_ = yield from self._call.__await__() except cygrpc.AioRpcError as aio_rpc_error: self._state = _RpcState.ABORT self._code = _common.CYGRPC_STATUS_CODE_TO_STATUS_CODE[ aio_rpc_error.code()] self._details = aio_rpc_error.details() self._initial_metadata = aio_rpc_error.initial_metadata() self._trailing_metadata = aio_rpc_error.trailing_metadata() # Propagates the pure Python class self._exception = AioRpcError(self._code, self._details, self._initial_metadata, self._trailing_metadata) raise self._exception from aio_rpc_error except asyncio.CancelledError as cancel_error: # _state, _code, _details are managed in the `cancel` method self._exception = cancel_error raise self._response = _common.deserialize(buffer_, self._response_deserializer) self._code = grpc.StatusCode.OK self._state = _RpcState.FINISHED return self._response
async def _invoke(self) -> ResponseType: serialized_request = _common.serialize(self._request, self._request_serializer) # NOTE(lidiz) asyncio.CancelledError is not a good transport for # status, since the Task class do not cache the exact # asyncio.CancelledError object. So, the solution is catching the error # in Cython layer, then cancel the RPC and update the status, finally # re-raise the CancelledError. serialized_response = await self._channel.unary_unary( self._method, serialized_request, self._deadline, self._cancellation, self._set_initial_metadata, self._set_status, ) await self._raise_rpc_error_if_not_ok() return _common.deserialize(serialized_response, self._response_deserializer)
async def _invoke(self) -> ResponseType: serialized_request = _common.serialize(self._request, self._request_serializer) # NOTE(lidiz) asyncio.CancelledError is not a good transport for status, # because the asyncio.Task class do not cache the exception object. # https://github.com/python/cpython/blob/edad4d89e357c92f70c0324b937845d652b20afd/Lib/asyncio/tasks.py#L785 try: serialized_response = await self._cython_call.unary_unary( serialized_request, self._set_initial_metadata, self._set_status, ) except asyncio.CancelledError: if self._code != grpc.StatusCode.CANCELLED: self.cancel() # Raises here if RPC failed or cancelled await self._raise_for_status() return _common.deserialize(serialized_response, self._response_deserializer)