diff --git a/server/api/websocket.py b/server/api/websocket.py index a91e1003..206e2e9d 100644 --- a/server/api/websocket.py +++ b/server/api/websocket.py @@ -60,9 +60,11 @@ class ConnectionManager: if conn: # Close the WebSocket to release the TCP connection try: - asyncio.get_event_loop().create_task( + asyncio.get_running_loop().create_task( conn["websocket"].close(code=1000, reason="cleanup") ) + except RuntimeError: + pass # No running event loop (e.g. during shutdown) except Exception: pass logger.info(f"WebSocket disconnected: {client_id}, total: {len(self._connections)}") diff --git a/server/infrastructure/ssh/asyncssh_pool.py b/server/infrastructure/ssh/asyncssh_pool.py index e501fe1d..7bab854e 100644 --- a/server/infrastructure/ssh/asyncssh_pool.py +++ b/server/infrastructure/ssh/asyncssh_pool.py @@ -98,28 +98,15 @@ class AsyncSSHPool: logger.debug(f"Reused SSH connection: server={server.id}, refs={pooled.ref_count}") return pooled.conn - # Need to create — evict if at capacity, then release lock for handshake + # Need to create — evict if at capacity if len(self._pool) >= self.MAX_CONNECTIONS: evicted = await self._evict_one() if not evicted: - # All connections are busy — wait for one to be released, then retry - logger.warning(f"SSH pool at capacity ({self.MAX_CONNECTIONS}), all busy — waiting") - - # If pool was full and all busy, wait briefly for a release before creating - if len(self._pool) >= self.MAX_CONNECTIONS: - for _ in range(3): # Wait up to 3 × 2s = 6s - await asyncio.sleep(2) - async with self._lock: - if len(self._pool) < self.MAX_CONNECTIONS: - break - await self._evict_one() - if len(self._pool) < self.MAX_CONNECTIONS: - break - else: - raise ConnectionError( - f"SSH pool at capacity ({self.MAX_CONNECTIONS}) and all connections busy. " - f"Try again later." - ) + # All connections are busy — cannot exceed MAX_CONNECTIONS + raise ConnectionError( + f"SSH pool at capacity ({self.MAX_CONNECTIONS}) and all connections busy. " + f"Try again later." + ) # Create connection outside lock (handshake can take seconds) conn = await self._create_connection(server)