modcomms/backend/app/websocket/manager.py
Vadym Samoilenko 5c338c31fb Fix WebSocket connection dropped during long proof analysis
- Add 25s heartbeat ping from backend to prevent Apache/proxy idle-timeout
  killing the connection during 1-3 min analysis runs
- Handle heartbeat silently in both analyzeProof and analyzeWIPProof frontend handlers
- Run PDF rasterization via asyncio.to_thread so heartbeats aren't blocked
- Wrap analyze_proof with asyncio.wait_for(timeout=300) for a hard 5-min cap
- Log dropped send_message calls in ConnectionManager instead of swallowing silently
- cloudrun.yaml: add sessionAffinity, startup probe, raise containerConcurrency 4→10,
  document DISABLE_AUTH option

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 11:23:59 +00:00

53 lines
1.6 KiB
Python
Executable file

import logging
from fastapi import WebSocket
logger = logging.getLogger(__name__)
class ConnectionManager:
"""Manages WebSocket connections for real-time updates."""
def __init__(self):
"""Initialize the connection manager."""
self.active_connections: dict[str, WebSocket] = {}
async def connect(self, websocket: WebSocket, client_id: str) -> None:
"""
Accept a new WebSocket connection.
Args:
websocket: The WebSocket connection
client_id: Unique identifier for this client
"""
await websocket.accept()
self.active_connections[client_id] = websocket
def disconnect(self, client_id: str) -> None:
"""
Remove a client connection.
Args:
client_id: The client to disconnect
"""
if client_id in self.active_connections:
del self.active_connections[client_id]
async def send_message(self, client_id: str, message: dict) -> None:
"""
Send a JSON message to a specific client.
Args:
client_id: The target client
message: Dictionary to send as JSON
"""
if client_id in self.active_connections:
try:
await self.active_connections[client_id].send_json(message)
except Exception as e:
logger.warning(f"[MANAGER] Failed to send message to client {client_id}: {e}")
self.disconnect(client_id)
def is_connected(self, client_id: str) -> bool:
"""Check if a client is still connected."""
return client_id in self.active_connections