Handling Server Calls
The server can call methods on the client in two ways: fire-and-forget notifications and client results (the server invokes a client method and waits for a return value).
Registering handlers
connection.on("target", handler)
When the server sends an Invocation (or StreamInvocation) for target,
every registered handler is called with the message arguments:
connection.on("message", lambda text: print("got:", text))
Handlers can be async:
async def on_file(path: str, size: int) -> None:
await save_file(path, size)
connection.on("fileReady", on_file)
For a fire-and-forget server call (invocation_id is None), all handlers run
and their return values are ignored.
Client results
When the server sends an invocation with an invocation id (client result), the handler's return value is sent back as the result:
async def client_method(text: str) -> str:
return f"ack:{text}"
connection.on("client_method", client_method)
- If exactly one handler returns a non-
Nonevalue, that value is sent as the result. - If no handler returns a value, an empty
Completionis sent. - If a handler raises, the client sends a
Completionwith the error message.
The server side uses clients.caller.invoke("client_method", ...) to trigger
this (see Client results).
Removing handlers
connection.remove("message", handler)
Unknown methods
If the server calls a method with no registered handler and an invocation id,
the client replies with a Completion carrying
"Unknown hub method '<target>'", which surfaces on the server as a
HubException.
Ordering
Handlers are invoked in registration order. Fire-and-forget notifications are dispatched as background tasks so a slow handler does not block frame processing.