How to close a loop event when executing an external function

Viewed 30

I am trying to play with asyncio and websockets those days and I am having troubles to reach a specific behaviour.

Context: I am subscribing to two streams that return timestamps: The stream "block_timestamp" return timestamps regularly, around each 2 sec. The stream "mint_start" will only return one timestamp at random time with a timestamp in the future.

Goal: When the "mint_start" timestamp is superior or equal to the "block_timstamp" timestamp, I would like to execute an other function.

Below is the event listener that works correctly:

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()
            await queue.put((id, message))

Here is the function that manage the timestamp returned by the two stream.

async def on_message(queue):
    while True:
        id, value = await queue.get()
        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 start_mint >= block_timestamp:
            # execute function

And finally the main function that run the two streams and the message handler concurently:

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)
    )

def run():
    asyncio.run(main())

When a specific condition is meet at on_message function level: start_mint >= block_timestamp, I would like to execute an other function. I would like to properly close the websocket and loop event that is running.

However so far I have no clue how to manage this correctly.

Thanks for the help

0 Answers
Related