When my client calls a server RPC, which then calls a client RPC, I can't await the return value from the client.
eg.:
WebsocketRPCEndpoint.main_loop
-> await channel handler
-> call client RPC
-> await result from client... Oh no, the main_loop is already awaiting! TIMEOUT!
I have "fixed" this for my usecase like so:
class AsyncWebsocketRPCEndpoint(WebsocketRPCEndpoint):
async def main_loop(self, websocket: WebSocket, client_id: str = None, **kwargs):
"""Override default main loop to handle nested RPC calls."""
try:
await self.manager.connect(websocket)
logger.info(f"Client connected", {"remote_address": websocket.client})
simple_websocket = self._serializing_socket_cls(
WebSocketSimplifier(websocket, frame_type=self._frame_type)
)
channel = RpcChannel(
self.methods,
simple_websocket,
sync_channel_id=self._rpc_channel_get_remote_id,
**kwargs,
)
# register connect / disconnect handler
channel.register_connect_handler(self._on_connect)
channel.register_disconnect_handler(self._on_disconnect)
await channel.on_connect()
async def handle_message_safely(data):
try:
await channel.on_message(data)
except Exception as e:
logger.exception(f"🔴 Unhandled error processing message: {e}")
try:
while True:
data = await simple_websocket.recv()
asyncio.create_task(handle_message_safely(data))
except WebSocketDisconnect:
logger.info(
f"Client disconnected - {websocket.client.port} :: {channel.id}"
)
await self.handle_disconnect(websocket, channel)
except:
# cover cases like - RuntimeError('Cannot call "send" once a close message has been sent.')
logger.info(
f"Client connection failed - {websocket.client.port} :: {channel.id}"
)
await self.handle_disconnect(websocket, channel)
except:
logger.exception(f"Failed to serve - {websocket.client.port}")
self.manager.disconnect(websocket)
I have no idea if this is robust for all cases and am not necessarily suggesting it as a change to the library, I don't have the braincells available to think this through deeply at the moment, but I am leaving this here so that anyone else which naively assumes that RPC's can be nested the way ordinary functions are can see this issue and possibly use this as a workaround for their code.
When my client calls a server RPC, which then calls a client RPC, I can't await the return value from the client.
eg.:
I have "fixed" this for my usecase like so:
I have no idea if this is robust for all cases and am not necessarily suggesting it as a change to the library, I don't have the braincells available to think this through deeply at the moment, but I am leaving this here so that anyone else which naively assumes that RPC's can be nested the way ordinary functions are can see this issue and possibly use this as a workaround for their code.