Update to v 0.4.0 #6

Merged
serversdown merged 21 commits from dev into main 2026-06-22 18:07:37 -04:00
Showing only changes of commit 5bc542e92f - Show all commits
+10
View File
@@ -284,10 +284,20 @@ async def monitor_stream(websocket: WebSocket, unit_id: str):
payload = await asyncio.wait_for(queue.get(), timeout=1.0) payload = await asyncio.wait_for(queue.get(), timeout=1.0)
except asyncio.TimeoutError: except asyncio.TimeoutError:
continue # re-check gone.done() continue # re-check gone.done()
if gone.done():
break # client disconnected while we waited — don't send into a closing socket
await websocket.send_json(payload) await websocket.send_json(payload)
except WebSocketDisconnect: except WebSocketDisconnect:
logger.info(f"Monitor subscriber disconnected for {unit_id}") logger.info(f"Monitor subscriber disconnected for {unit_id}")
except Exception as e: except Exception as e:
# A frame that races the close (client vanished mid-send) surfaces as
# "Unexpected ASGI message 'websocket.send' after ... websocket.close".
# That's expected on disconnect (the portal closes the socket on every tab
# switch), not an error — log it quietly.
msg = str(e)
if "after sending" in msg or "websocket.close" in msg or "response already completed" in msg:
logger.debug(f"Monitor stream for {unit_id} closed mid-send (client gone)")
else:
logger.warning(f"Monitor stream error for {unit_id}: {e}") logger.warning(f"Monitor stream error for {unit_id}: {e}")
finally: finally:
gone.cancel() gone.cancel()