This commit is contained in:
2026-04-01 18:31:33 +02:00
parent 6e23e32bb0
commit b5c7c5305a
95 changed files with 9609 additions and 2374 deletions

View File

@@ -0,0 +1,41 @@
"""
Manages persistent per-user WebSocket connections for the notification channel.
The DB is the source of truth — this layer just delivers live pushes to connected clients.
"""
import logging
from fastapi import WebSocket
logger = logging.getLogger("app")
# user_id (str) -> active WebSocket; replaced on reconnect
connections: dict[str, WebSocket] = {}
def register(user_id: str, ws: WebSocket) -> None:
connections[user_id] = ws
def unregister(user_id: str) -> None:
connections.pop(user_id, None)
async def send_notification(user_id: str, notification: dict) -> None:
"""Push a single notification to the user if they're connected. No-op otherwise."""
ws = connections.get(user_id)
if ws:
try:
await ws.send_json({"type": "push", "notification": notification})
except Exception as e:
# Stale connection — the disconnect handler will clean it up
logger.debug(f"WebSocket send failed (stale connection): {e}")
async def send_delete(user_id: str, notification_id: str) -> None:
"""Tell the client to remove a notification from its local list."""
ws = connections.get(user_id)
if ws:
try:
await ws.send_json({"type": "delete", "notification_id": notification_id})
except Exception as e:
logger.debug(f"WebSocket send failed (stale connection): {e}")