Fix ws error

This commit is contained in:
Xin Wang
2026-02-09 15:53:21 +08:00
parent 8fd6daaed1
commit cb5c08d84d

View File

@@ -69,6 +69,13 @@ class SocketTransport(BaseTransport):
self.lock = asyncio.Lock() # Prevent frame interleaving
self._closed = False
def _ws_disconnected(self) -> bool:
"""Best-effort check for websocket disconnection state."""
return (
self.ws.client_state == WebSocketState.DISCONNECTED
or self.ws.application_state == WebSocketState.DISCONNECTED
)
async def send_event(self, event: dict) -> None:
"""
Send a JSON event via WebSocket.
@@ -76,17 +83,27 @@ class SocketTransport(BaseTransport):
Args:
event: Event data as dictionary
"""
if self._closed:
if self._closed or self._ws_disconnected():
logger.warning("Attempted to send event on closed transport")
self._closed = True
return
async with self.lock:
try:
await self.ws.send_text(json.dumps(event))
logger.debug(f"Sent event: {event.get('event', 'unknown')}")
except Exception as e:
logger.error(f"Error sending event: {e}")
except RuntimeError as e:
self._closed = True
if self._ws_disconnected() or "close message has been sent" in str(e):
logger.debug(f"Skip sending event on closed websocket: {e!r}")
return
logger.error(f"Error sending event: {e!r}")
except Exception as e:
self._closed = True
if self._ws_disconnected():
logger.debug(f"Skip sending event on disconnected websocket: {e!r}")
return
logger.error(f"Error sending event: {e!r}")
async def send_audio(self, pcm_bytes: bytes) -> None:
"""
@@ -95,16 +112,26 @@ class SocketTransport(BaseTransport):
Args:
pcm_bytes: PCM audio data (16-bit, mono, 16kHz)
"""
if self._closed:
if self._closed or self._ws_disconnected():
logger.warning("Attempted to send audio on closed transport")
self._closed = True
return
async with self.lock:
try:
await self.ws.send_bytes(pcm_bytes)
except Exception as e:
logger.error(f"Error sending audio: {e}")
except RuntimeError as e:
self._closed = True
if self._ws_disconnected() or "close message has been sent" in str(e):
logger.debug(f"Skip sending audio on closed websocket: {e!r}")
return
logger.error(f"Error sending audio: {e!r}")
except Exception as e:
self._closed = True
if self._ws_disconnected():
logger.debug(f"Skip sending audio on disconnected websocket: {e!r}")
return
logger.error(f"Error sending audio: {e!r}")
async def close(self) -> None:
"""Close the WebSocket connection."""
@@ -112,10 +139,7 @@ class SocketTransport(BaseTransport):
return
self._closed = True
if (
self.ws.client_state == WebSocketState.DISCONNECTED
or self.ws.application_state == WebSocketState.DISCONNECTED
):
if self._ws_disconnected():
return
try: