init
This commit is contained in:
41
backend/ws.py
Normal file
41
backend/ws.py
Normal file
@@ -0,0 +1,41 @@
|
||||
"""Live-Board-Hub: Statuswechsel aus der DB-Schicht → alle WebSocket-Clients.
|
||||
Kein Polling; das Frontend hält den Snapshot und wendet Deltas an."""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
|
||||
log = logging.getLogger("creator2.ws")
|
||||
|
||||
|
||||
class Hub:
|
||||
def __init__(self):
|
||||
self._clients: set = set()
|
||||
self._loop: asyncio.AbstractEventLoop | None = None
|
||||
|
||||
def bind_loop(self, loop: asyncio.AbstractEventLoop) -> None:
|
||||
self._loop = loop
|
||||
|
||||
async def connect(self, websocket) -> None:
|
||||
await websocket.accept()
|
||||
self._clients.add(websocket)
|
||||
|
||||
def disconnect(self, websocket) -> None:
|
||||
self._clients.discard(websocket)
|
||||
|
||||
def push(self, tabelle: str, row: dict) -> None:
|
||||
"""Thread-sicher (DB-Schicht ruft synchron): auf den Loop dispatchen."""
|
||||
if not self._clients or self._loop is None:
|
||||
return
|
||||
msg = json.dumps({"tabelle": tabelle, "row": row}, ensure_ascii=False, default=str)
|
||||
self._loop.call_soon_threadsafe(lambda: asyncio.ensure_future(self._send_all(msg)))
|
||||
|
||||
async def _send_all(self, msg: str) -> None:
|
||||
for ws in list(self._clients):
|
||||
try:
|
||||
await ws.send_text(msg)
|
||||
except Exception:
|
||||
self._clients.discard(ws)
|
||||
|
||||
|
||||
hub = Hub()
|
||||
Reference in New Issue
Block a user