1

This is my first experience with websockets, and I'm not completely sure I am doing everything correctly. However, when reloading the web browser, the reconnects to the websocket. When this happens I have a list of messages from previous sessions and I send them back. At the moment, there are only 3, but the browser does not receive all 3 of them.

I am using FastAPI, and my send/receive code looks like this:

@app.websocket_route("/ws")
async def websocket_endpoint(websocket: WebSocket):
    ws_active = False

    # when establishing the websocket, query the devices online
    # but only if it's the first connection
    device_report()

    # accept the websocket connection
    await websocket.accept()
    ws_active = True
    # Push message history to client
    async def send(message):
        nonlocal ws_active
        await push_messages(websocket)
        try:
            while ws_active:
                # Check if there are any messages in the queue
                if not queue().empty():
                    message = await queue().get()
                    print('get: ' + message)
                    if ws_active:
                        await websocket.send_text(message)

                # Wait for new messages to arrive in the queue
                message = await queue().get()
                if ws_active:
                    print('get2: ' + message)
                    await websocket.send_text(message)

        except WebSocketDisconnect:
            try:
                await websocket.close()
                ws_active = False
            except:
                pass


    async def receive():
        nonlocal ws_active
        try:
            while ws_active:
                data_in = await websocket.receive_json()
                print(data_in)
        except WebSocketDisconnect:
            try:
                await websocket.close()
                ws_active = False
            except:
                pass
    try:
        await asyncio.gather(send('{asd:asd}'), receive())
    except:
        pass

the function push_messages is simple and it just takes the array of data and puts them in the queue.

async def push_messages(self, websocket: WebSocket):
    for message in self.can_messages:
        print('push: ' + message)
        await self.message_queue.put(message)
    for message in self.all_messages:
        await self.message_queue.put(message)

Reloading the browser I see these output on the python console:

push: {"type": "can", "msg": "Supervisor reported online."}
push: {"type": "can", "msg": "ECU 1 reported online."}
push: {"type": "can", "msg": "ECU 2 reported online."}
get2: {"type": "can", "msg": "Supervisor reported online."}
get: {"type": "can", "msg": "ECU 1 reported online."}
get2: {"type": "can", "msg": "ECU 2 reported online."}

The push is going to the queue object and the get is receiving them. In the browser's javascript console I see only two are received:

enter image description here

From everything I've read, the connection is established and there isn't any kind of "check" to make sure it's ready for sending and receiving.

However, if I put an arbitrary: await asyncio.sleep(1) at the beginning of the send() function this seems to result in all the messages being sent. But that's a terrible solution and waiting for 1 second on every page reload/navigation is dumb.

Is there some other way I can approach this to get all the messages on a reload/navigation change?

Chris
  • 18,724
  • 6
  • 46
  • 80
jgauthier
  • 422
  • 3
  • 14
  • Does this answer your question? [How to get the updated list of items in Jinja2 template using FastAPI?](https://stackoverflow.com/questions/70991467/how-to-update-jinja-variable-in-loop-using-fastapi) – Chris Mar 08 '23 at 19:04

0 Answers0