"""WebSocket 实时推送""" import asyncio import json import logging import redis.asyncio as aioredis from fastapi import APIRouter, WebSocket, WebSocketDisconnect from app.core.config import settings logger = logging.getLogger(__name__) router = APIRouter(prefix="/api", tags=["WebSocket"]) REDIS_CHANNEL = "h3c_onu:status_updates" _connected: set[WebSocket] = set() async def _redis_listener(): """监听 Redis pub/sub 并广播给所有 WebSocket 客户端""" try: r = aioredis.from_url(settings.REDIS_URL) pubsub = r.pubsub() await pubsub.subscribe(REDIS_CHANNEL) logger.info("WebSocket Redis 监听已启动") async for msg in pubsub.listen(): if msg["type"] == "message": dead: set[WebSocket] = set() for ws in _connected: try: await ws.send_text(msg["data"].decode()) except Exception: dead.add(ws) _connected -= dead except Exception as e: logger.error(f"Redis 监听异常: {e}") @router.websocket("/ws/dashboard") async def dashboard_ws(ws: WebSocket): await ws.accept() _connected.add(ws) try: while True: await ws.receive_text() # keep-alive, 忽略客户端消息 except WebSocketDisconnect: pass finally: _connected.discard(ws)