47 lines
1.5 KiB
Python
47 lines
1.5 KiB
Python
"""WS-Hub (R1): EINE Queue + EIN Sender-Task — Broadcasts bleiben geordnet.
|
|
Payload ist nur ein dirty-Signal {typ, topic, bereich}; der Client lädt selbst."""
|
|
import asyncio
|
|
import json
|
|
|
|
|
|
class Hub:
|
|
def __init__(self) -> None:
|
|
self._clients: set = set()
|
|
self._queue: asyncio.Queue | None = None
|
|
self._loop: asyncio.AbstractEventLoop | None = None
|
|
|
|
def bind_loop(self, loop: asyncio.AbstractEventLoop) -> None:
|
|
self._loop = loop
|
|
self._queue = asyncio.Queue()
|
|
loop.create_task(self._sende_schleife())
|
|
|
|
def push(self, tabelle: str, row: dict) -> None:
|
|
"""Thread-sicher aus der DB-Schicht aufrufbar."""
|
|
if self._loop is None or self._queue is None:
|
|
return
|
|
from . import db
|
|
bereich = "run" if tabelle in db._RUN_TABELLEN else "graph"
|
|
msg = json.dumps({"typ": "dirty", "bereich": bereich}, ensure_ascii=False)
|
|
self._loop.call_soon_threadsafe(self._queue.put_nowait, msg)
|
|
|
|
async def _sende_schleife(self) -> None:
|
|
while True:
|
|
msg = await self._queue.get()
|
|
tot = []
|
|
for ws in list(self._clients):
|
|
try:
|
|
await ws.send_text(msg)
|
|
except Exception:
|
|
tot.append(ws)
|
|
for ws in tot:
|
|
self._clients.discard(ws)
|
|
|
|
def connect(self, ws) -> None:
|
|
self._clients.add(ws)
|
|
|
|
def disconnect(self, ws) -> None:
|
|
self._clients.discard(ws)
|
|
|
|
|
|
hub = Hub()
|