Websockets client: how to properly manage the connection and auto re-connection

Viewed 27

I started to implement a websocket client via Websockets, this is working however I am not satisfied yet and I am strugleling to know what are the good practice. Please find below the current code. I subscribe to two different channels:

-> block_timestamp: Get timestamps that are pushed around each 2sec

-> mint_start: Get a timesteamp that is pushed only once

Those data are managed via on_message function and as soon as: mint_start >= block_timestamp, it should execute an external function.

async def event_listener(id, params, queue):
    async with websockets.connect(url) as ws:

        await ws.send(json.dumps({"id": 1, "method": "eth_subscribe", "params": params}))
        subscription_response = await ws.recv()
        subscription_response = json.loads(subscription_response)

        if subscription_response.get("error"):
            return subscription_response["error"]["code"], subscription_response["error"]["message"]
        else:
            print(f"Subscribed with success to stream id: {subscription_response['result']}")

        while True:
            message = await ws.recv()
            print(message)
            await queue.put((id, message))
async def on_message(queue):
    block_timestamp, start_mint = None, None
    a = True
    while a:
        id, value = await queue.get()
        print(id, value)
        if id == "block_timestamp":
            block_timestamp = (json.loads(value)['params']['result']["timestamp"])
        else:
            start_mint = (decode_single('(uint112,uint112)', bytearray.fromhex(value['params']['result']['data'][2:])))

        if block_timestamp is not None:
            #execute a function
async def main():
    params1 = ["newHeads"]
    params2 = ["logs", {"address": ["0xf4003f4efbe8691b60249e6afbd307abe7758adb"],
                        "topics": [Web3.keccak(text="Sync(uint112,uint112)").hex()]}]

    queue = asyncio.Queue()
    await asyncio.gather(
        event_listener("block_timestamp", params1, queue),
        event_listener("mint_start", params2, queue),
        on_message(queue)
    )
if __name__ == "__main__":
  asyncio.run(main())

According to me, when this code is is executed, two connections are made to the websockets. So this is not good, as only one connection is necessary.How could I manage this connection to be done only once ?

In addition, I would like to auto-reconnect automatically in case the connected stop. Would you have an idea of how it can be done properly ?

To finish, when the condition is meet (mint_start >= block_timestamp), the code will execute an external function. I would also like to stop the websocket connection and also the tasks running. But I have trouble to manage it correctly via asyncio.

A bit of help would be much appreaciated ! Thanks

0 Answers
Related