MCPcopy Create free account
hub / github.com/dbunt1tled/python-fast-api / WSManager

Class WSManager

src/core/web_socket/ws_manager.py:9–101  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

7
8
9class WSManager:
10 MAX_CONNECTIONS: ClassVar[int] = 1000
11 def __init__(
12 self,
13 log: Log,
14 ) -> None:
15 self._connections: dict[str, list[tuple[WebSocket, asyncio.Lock]]] = {}
16 self._lock = asyncio.Lock()
17 self.log = log
18
19 async def connect(self, user_id: str, websocket: WebSocket) -> None:
20 if len(self._connections) >= self.MAX_CONNECTIONS:
21 await websocket.close(code=status.WS_1008_POLICY_VIOLATION) # Connection limit exceeded
22 self.log.error(f"🥕 WebSocket connect: user {user_id}, connection limit exceeded")
23 return
24 await websocket.accept()
25 async with self._lock:
26 lock = asyncio.Lock()
27 self._connections.setdefault(user_id, []).append((websocket, lock))
28 self.log.info(f"🍏 WebSocket connected: {user_id} (total {len(self._connections.get(user_id, []))})")
29
30 async def disconnect(self, user_id: str, websocket: WebSocket) -> None:
31 async with self._lock:
32 conns = self._connections.get(user_id, [])
33 conns = [c for c in conns if c[0] is not websocket]
34 if not conns:
35 self._connections.pop(user_id, None)
36 try:
37 await websocket.close(code=status.WS_1000_NORMAL_CLOSURE)
38 except Exception as e:
39 self.log.warning(f"🫜 WebSocket failed to close to {user_id}: {e}")
40 self.log.info(f"🍎 WebSocket disconnected: {user_id}")
41
42 async def send_to_user(self, user_id: str, data: dict[str, Any], websocket: WebSocket | None = None) -> int:
43 conns = self._connections.get(user_id, [])
44 if not conns:
45 self.log.debug(f"🍊 WebSocket No active ws for user {user_id}")
46 return 0
47 if websocket is not None:
48 wss = [c for c in conns if c[0] is websocket]
49 if not wss:
50 self.log.debug(f"🍊 WebSocket No active ws for user {user_id}")
51 return 0
52 success = int(await self._safe_send(wss[0], data, user_id))
53 else:
54 coros = [self._safe_send(ws, data, user_id) for ws in conns]
55 results = await asyncio.gather(*coros, return_exceptions=True)
56 success = sum(1 for r in results if r is True)
57 self.log.info(f"🍐 WebSocket sent message to {success}/{len(conns)} connections for user {user_id}")
58 return success
59
60 async def broadcast(self, data: dict[str, Any], exclude_user_id: list[str] | None = None) -> int:
61 if exclude_user_id is None:
62 exclude_user_id = []
63 success = 0
64 user_ids = []
65 for user_id in self._connections.keys():
66 if user_id in exclude_user_id:

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected