explodinglabs / jsonrpcclient

Generate JSON-RPC requests and parse responses in Python

Home Page:https://www.jsonrpcclient.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

WebSocket race condition. Unexpected behaviour.

sergio-bershadsky opened this issue · comments

https://github.com/bcb/jsonrpcclient/blob/34951af900a663020c40896cbc7637ca710aa4d7/jsonrpcclient/clients/websockets_client.py#L40

Subject could happen if websocket used with several send execution (for ex. gather)

Case description:
Client sends requests with ids 1, 2, 3 and it receives back responses in order 3, 2, 1:
second response will be swapped with 3rd one.

Suggestions:

  1. Additional queue object must be implemented to store responses as a sub loop.
  2. Match request_id in responses and return it back only if ids matched
  3. Use wait_for to support timeouts.
  4. Track waiting ids and delete all responses that came after timeout happened.

P.S. I will try to create working example in couple days

commented

This is the nature of websockets, responses may not arrive in the order requests were sent.

request id could be used as synchronization object. The only thing is to write proper response waiter.

jsonrpc doesn't require anything about response order, and jsonrpcclient appears to assume the next incoming message must be a response to the currently pending request. This holds true if you await all responses before making a new request, and also assumes all incoming messages on the transport are jsonrpc responses.

Looks like a huge problem. I need to send lots of requests without waiting responses and these responses may appear outside of initial order (e.g. they can took different time to execute at server side). Like this:

--> 1
--> 2
--> 3
--> 4

<-- 3
<-- 1
<-- 4
<-- 2

Another problem I got is that I cannot send multiple requests from several coroutines concurrently using WebSocketsClient due to error cannot call recv() while another coroutine is already waiting for the next message

commented

Ok I see the issue.

Jsonrpcclient is sending a request, then receiving a response, which may not relate to the request.

Really jsonrpcclient should only send requests. It should not receive a response. This can be left to the implementations.

Really jsonrpcclient should only send requests. It should not receive a response. This can be left to the implementations.

I suggest removing the whole response = client.request(...) api because it makes things really confusing

commented

It makes sense for the synchronous protocols, but for the asynchronous ones I agree.

commented

Clients being removed from v4 #171