🐐
This commit is contained in:
41
backend/services/notification_manager.py
Normal file
41
backend/services/notification_manager.py
Normal 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}")
|
||||
Reference in New Issue
Block a user