0

I am trying to build a websocket. In this websocket i have two operation. İf client send me "orderbook" input, i am returning data from redis - (channel-1). If client send me "ticker" input, i am returning data from redis - (channel-2).

I can use this websocket but it's not working when one operation is online. For example if i connected with "ticker" input it's ok. But after that i cant get any operations with my websocket. I want the use 2 operation in same time or same operation in same time. But it's only working with 1 operation.

This is my websocket script

import asyncio import json import websockets import redis import yaml

with open('config.yaml') as f:
    config = yaml.load(f, Loader=yaml.FullLoader)

r = redis.Redis(host=config["redis_host"], port=config["redis_port"], db=0, password=config["redis_password"])
rr = redis.Redis(host=config["redis_host"], port=config["redis_port"], db=0, password=config["redis_password"])

p = r.pubsub()
pp = rr.pubsub()

p.subscribe(config["redis_channel_name_orderbook"])
pp.subscribe(config["redis_channel_name_ticker"])


async def hello(websocket):
    data = await websocket.recv()

    if data == "orderbook":
        while True:
            message = p.get_message()

            if message:
                if type(message["data"]) == bytes:
                    message["data"] = bytes.decode(message["data"])

                message = json.dumps(message["data"])
                await websocket.send(message)

    elif data == "ticker":
        while True:
            message = pp.get_message()

            if message:
                if type(message["data"]) == bytes:
                    message["data"] = bytes.decode(message["data"])

                # message = json.dumps(message["data"])
                await websocket.send(message["data"])


async def main():
    async with websockets.serve(hello, config["redis_host"], config["websocket_port"]):
        await asyncio.Future()  # run forever


if __name__ == "__main__":
    asyncio.run(main())

What could be wrong with this script ?

Selman
  • 274
  • 2
  • 4
  • 17
  • What is the exact error you are getting? – Václav Jul 22 '22 at 09:17
  • While a client is open and data is flowing from the websocket to it, my other connection requests are not working. There is no error message either. When I close the first client I connected, it connects to the newly opened websocket. – Selman Jul 22 '22 at 09:19
  • Firefox can’t establish a connection to the server at ws://localhost:8765/. – Selman Jul 22 '22 at 09:40
  • `while True` can block all code and it can't work with other users. It may need to run loops in separated threads. Do you really have to run it in loop? OR maybe you should use `await asyncio.sleep()` when there is no message - this way asyncio will have time to switch to other users – furas Jul 22 '22 at 09:42

1 Answers1

0

The problem imho is that you are using await run your code. await by definition is waiting for the task to finish rather than spawning a separate task without waiting for the result. You don't want to wait for the task to finish (your code doesn't rely on that). And that probably blocks your websocket client from working with multiple tasks at once.

You can try this approach, that is using the asyncio.create_task for a similar problem and it should be working for you.

Václav
  • 990
  • 1
  • 12
  • 28
  • i changed data = await websocket.recv() to data = asyncio.create_task(websocket.recv()). Now something strange happened. When I open only one client, there is no data return. – Selman Jul 22 '22 at 09:35
  • I think you are not receiving the data after you send the task. Can you check `asyncio.gather()`? That should gather the result of the `.recv()` operation. – Václav Jul 22 '22 at 09:36
  • As described in this answer - https://stackoverflow.com/a/52252278/10556960 – Václav Jul 22 '22 at 09:46