Need clarification on asyncio.Condition (original) (raw)

Recently I done a program with quart (web server framework) that allows admins to broadcast messages like so.

data = "string"
broadcast_condition = asyncio.Condition

@app.post("/admin/update_secret")
@login_required
async def update_secret():
    global data
    # ... parse data
    data = new_value
    async with broadcast_condition:
        broadcast_condition.notify_all()

@app.websocket('/ws')
async def ws():
    websocket.accept()
    await websocket.send(data)
    async with broadcast_condition:
        while (await broadcast_condition.wait()):
            await websocket.send(data)

What the program does is whenever update_secret() is called, all websocket client on ws() should receive a copy and the code looks neat… that’s what I thought.

I have a few question with this code:

  1. what if update_secret() is spammed very frequently, like for every websocket.send() is processed there are two notify_all() calls, does the while loop only process once in this case?
  2. What if an admin disconnects (e.g. bad Wi-Fi) while quart is doing notify_all(), and quart cancels asyncio task (asyncio.CancelledError is thrown) before notify_all() is complete? does some client not get notified in that case?
  3. does notify_all() call take more time if more websocket client wait on the condition? (10 clients vs 200 clients?, is it posiible that webserver times out update_secret() because it takes too long)
  4. Is it possible that notify_all() only ensure every client executes at least once? Like it doesn’t care if client A’s while loop executes 100 times before executing client B’s while loop? and after notify_all() completes different client receives message different times.