feat(collector): add websocket
This commit is contained in:
60
services/collector/ws_manager.py
Normal file
60
services/collector/ws_manager.py
Normal file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python3
|
||||
"""WebSocket connection manager for broadcasting live audio data."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from starlette.websockets import WebSocket, WebSocketState
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ConnectionManager:
|
||||
"""Manages WebSocket connections and broadcasts messages to all clients."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._clients: set[WebSocket] = set()
|
||||
self._lock = asyncio.Lock()
|
||||
|
||||
async def connect(self, ws: WebSocket) -> None:
|
||||
"""Accept and register new WebSocket connection."""
|
||||
await ws.accept()
|
||||
async with self._lock:
|
||||
self._clients.add(ws)
|
||||
logger.info("WS client connected (total=%d)", len(self._clients))
|
||||
|
||||
async def disconnect(self, ws: WebSocket) -> None:
|
||||
"""Remove WebSocket connection."""
|
||||
async with self._lock:
|
||||
self._clients.discard(ws)
|
||||
logger.info("WS client disconnected (total=%d)", len(self._clients))
|
||||
|
||||
async def broadcast_json(self, message: dict[str, Any]) -> None:
|
||||
"""Broadcast JSON message to all connected clients."""
|
||||
if not self._clients:
|
||||
return
|
||||
|
||||
payload = json.dumps(message, ensure_ascii=False, separators=(",", ":"))
|
||||
|
||||
async with self._lock:
|
||||
clients = list(self._clients)
|
||||
|
||||
dead: list[WebSocket] = []
|
||||
for ws in clients:
|
||||
try:
|
||||
if ws.client_state == WebSocketState.CONNECTED:
|
||||
await ws.send_text(payload)
|
||||
else:
|
||||
dead.append(ws)
|
||||
except Exception:
|
||||
dead.append(ws)
|
||||
|
||||
if dead:
|
||||
async with self._lock:
|
||||
for ws in dead:
|
||||
self._clients.discard(ws)
|
||||
logger.debug("WS cleanup: removed %d dead clients", len(dead))
|
||||
Reference in New Issue
Block a user