Reputation: 2072
I am using Python 3.6, asyncio and the websockets library. I am trying to build a client for a websocket-based service which works as follows:
The client can send JSON requests with a custom id
, a method
and some params
. The service will reply with a JSON payload with the same id
echoed, and data
as a result of the method call.
I would like to have an abstraction on top of this device that would work sort of like this:
wsc = get_websocket_connection()
async def call_method(method, **params):
packet = make_json_packet(method, params)
await wsc.send(packet)
resp = await wsc.recv()
return decode_json_packet(resp)
async def working_code():
separate_request = asyncio.ensure_future(call_method("quux"))
first_result = await call_method("foo", x=1)
second_result = await call_method("bar", y=first_result)
print(second_result)
return await separate_request
Now, I expect the separate_request
to wait asynchronously while first_result
and second_result
s are processed. But I have no guarantee that the wsc.recv()
call will return the matching response; in fact, I have no guarantees that the service returns the responses in order of requests.
I can use the id
field to disambiguate the responses. But how can I write the call_method()
so that it manages the requests internally and resumes the "right" coroutine when the corresponding reply is received?
Upvotes: 1
Views: 868
Reputation: 16213
when I've done this sort of thing before I've tended to split things out into two parts:
dict
of id
s to functions or Future
s), then sends the request and blocks for the responseid
. this is also a sensible place to handle the socket being closed unexpectedly which should push an exception out as appropriatethis is probably a few hundred lines of code and pretty application specific…
Upvotes: 1