async def call_rpc_remote(self, api_name: str, name: str, kwargs: dict, options: dict): rpc_message = RpcMessage(api_name=api_name, procedure_name=name, kwargs=kwargs) return_path = self.result_transport.get_return_path(rpc_message) rpc_message.return_path = return_path options = options or {} timeout = options.get('timeout', 5) logger.info("➡ Calling remote RPC ".format(rpc_message)) start_time = time.time() # TODO: It is possible that the RPC will be called before we start waiting for the response. This is bad. future = asyncio.gather( self.receive_result(rpc_message, return_path, options=options), self.rpc_transport.call_rpc(rpc_message, options=options), ) await plugin_hook('before_rpc_call', rpc_message=rpc_message, bus_client=self) try: result_message, _ = await asyncio.wait_for(future, timeout=timeout) except asyncio.TimeoutError: future.cancel() # TODO: Include description of possible causes and how to increase the timeout. # TODO: Remove RPC from queue. Perhaps add a RpcBackend.cancel() method. Optional, # as not all backends will support it. No point processing calls which have timed out. raise LightbusTimeout('Timeout when calling RPC {} after {} seconds'.format( rpc_message.canonical_name, timeout )) from None await plugin_hook('after_rpc_call', rpc_message=rpc_message, result_message=result_message, bus_client=self) if not result_message.error: logger.info(L("⚡ Remote call of {} completed in {}", Bold(rpc_message.canonical_name), human_time(time.time() - start_time))) else: logger.warning( L("⚡ Server error during remote call of {}. Took {}: {}", Bold(rpc_message.canonical_name), human_time(time.time() - start_time), result_message.result, ), ) raise LightbusServerError('Error while calling {}: {}\nRemote stack trace:\n{}'.format( rpc_message.canonical_name, result_message.result, result_message.trace, )) return result_message.result
async def call_rpc_remote(self, api_name: str, name: str, kwargs: dict = frozendict(), options: dict = frozendict()): rpc_transport = self.transport_registry.get_rpc_transport(api_name) result_transport = self.transport_registry.get_result_transport( api_name) kwargs = deform_to_bus(kwargs) rpc_message = RpcMessage(api_name=api_name, procedure_name=name, kwargs=kwargs) return_path = result_transport.get_return_path(rpc_message) rpc_message.return_path = return_path options = options or {} timeout = options.get("timeout", self.config.api(api_name).rpc_timeout) self._validate_name(api_name, "rpc", name) logger.info("📞 Calling remote RPC {}.{}".format( Bold(api_name), Bold(name))) start_time = time.time() # TODO: It is possible that the RPC will be called before we start waiting for the response. This is bad. self._validate(rpc_message, "outgoing") future = asyncio.gather( self.receive_result(rpc_message, return_path, options=options), rpc_transport.call_rpc(rpc_message, options=options), ) await self._plugin_hook("before_rpc_call", rpc_message=rpc_message) try: result_message, _ = await asyncio.wait_for(future, timeout=timeout) future.result() except asyncio.TimeoutError: # Allow the future to finish, as per https://bugs.python.org/issue29432 try: await future future.result() except CancelledError: pass # TODO: Remove RPC from queue. Perhaps add a RpcBackend.cancel() method. Optional, # as not all backends will support it. No point processing calls which have timed out. raise LightbusTimeout( f"Timeout when calling RPC {rpc_message.canonical_name} after {timeout} seconds. " f"It is possible no Lightbus process is serving this API, or perhaps it is taking " f"too long to process the request. In which case consider raising the 'rpc_timeout' " f"config option.") from None await self._plugin_hook("after_rpc_call", rpc_message=rpc_message, result_message=result_message) if not result_message.error: logger.info( L( "🏁 Remote call of {} completed in {}", Bold(rpc_message.canonical_name), human_time(time.time() - start_time), )) else: logger.warning( L( "⚡ Server error during remote call of {}. Took {}: {}", Bold(rpc_message.canonical_name), human_time(time.time() - start_time), result_message.result, )) raise LightbusServerError( "Error while calling {}: {}\nRemote stack trace:\n{}".format( rpc_message.canonical_name, result_message.result, result_message.trace)) self._validate(result_message, "incoming", api_name, procedure_name=name) return result_message.result