Sanic websocket connections

Hello every one. I try to send json data from my http route which do some logic and after finishing operation send data to websocket channel. This websocket channel send data and frontend listening changes.

@app.route("/text", methods=[“POST”])
async def handler_text(request):
#some logic manipulations

    ws = await websockets.client.connect('ws://localhost:5003/backend/alert/message')
    print('Connected to alert ws')
    await ws.send(json({'message': 'Create new data from db'}))
    return response.text("Hello")


@app.websocket("/message")
async def handler_ws(request, ws):
    print("Websocket opened")
    name = "<someone>"
    while True:
        data = f"Hello {name}"
        await ws.send(data)
        name = await ws.recv()

        if not name:
            break

But when i send post request it’s try to connect but process stopped on connections moment. I try to connect without await and with closing connections after sending data on ‘/test’ endpoint.
How can i send data from my http rout to websocket?

I’m somewhat confused here. The frontend posts to the POST message, but is also listening on the websocket. And you are expecting the post endpoint to be able to push to the socket? Did I get that correct?

If so, then you need another strategy to be able to pass data from one connection to another. Perhaps if you are on a single instance, you could easily do this with a queue. But to get a more complete and production worthy solution, I would look at websockets with a pubsub (which your POST endpoint could publish to).

Take a look at this to see if it helps

I wont to notify my wesocket to send message in channel, when something happened on other endpoint. Websockets and http riutes contains in one applications.

That’s what I thought. That gist (or something like it) should be what you want.

As i understand queues help me to solve this issues?
I add listener and queue:
@app.listener(‘after_server_start’)
async def create_task_queue(app, loop):
app.queue = asyncio.Queue(loop=loop, maxsize=10)

@app.websocket('/backend/alert/message')
async def alerts_hendler_ws(request, ws):
    data = await request.app.queue.get()
    app.queue.task_done()
    await ws.send(data)

And method with queue fill:
def update(self):
app.queue.put({‘message’: ‘Alerts create’})

Yes, absolutely. Here’s a similar solution using queues: How to use asyncio queues in Sanic?

The problem there though is that it is not horizontally scalable. If you intend this for production use, I would suggest a pubsub or other platform like rabbitmq.

Thank you very much!

1 Like