Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling disconnects #87

Closed
darabos opened this issue Nov 29, 2024 · 0 comments · Fixed by #94
Closed

Handling disconnects #87

darabos opened this issue Nov 29, 2024 · 0 comments · Fixed by #94
Labels
bug Something isn't working

Comments

@darabos
Copy link
Contributor

darabos commented Nov 29, 2024

Sorry, I'm not sure it's a bug, but I can't figure out how to handle disconnects.

    | Traceback (most recent call last):
    |   File "python3.11/site-packages/pycrdt_websocket/asgi_server.py", line 33, in send
    |     await self._send(
    |   File "python3.11/site-packages/starlette/_exception_handler.py", line 48, in sender
    |     await send(message)
    |   File "python3.11/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 358, in asgi_send
    |     raise RuntimeError(msg % message_type)
    | RuntimeError: Unexpected ASGI message 'websocket.send', after sending 'websocket.close' or response already completed.

I'm not following the examples exactly, because I'm using pycrdt in an existing FastAPI application. My code looks basically like this:

router = fastapi.APIRouter()
def ws_exception_handler(exception, log):
    print("exception", exception)
    return True
class WebsocketServer(pycrdt_websocket.WebsocketServer):
    # ... overrides init_room() and get_room() to set up my documents ...
websocket_server = WebsocketServer(
    exception_handler=ws_exception_handler, auto_clean_rooms=False
)
asgi_server = pycrdt_websocket.ASGIServer(websocket_server)

@contextlib.asynccontextmanager
async def lifespan(app):
    async with websocket_server:
        yield

@router.websocket("/ws/crdt/{room_name}")
async def crdt_websocket(websocket: fastapi.WebSocket, room_name: str):
    await asgi_server({"path": room_name}, websocket._receive, websocket._send)

I see asgi_server() has an on_disconnect argument, but what would I do on disconnect? I'm not maintaining a list of websockets.

The whole thing works other than these errors. And I'm only seeing them because of the custom error handler. But I'm seeing hundreds of these exceptions. Sometimes I get variations, like:

| Traceback (most recent call last):
|   File "python3.11/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 330, in asgi_send
|     await self.send(data)  # type: ignore[arg-type]
|     ^^^^^^^^^^^^^^^^^^^^^
|   File "python3.11/site-packages/websockets/legacy/protocol.py", line 628, in send
|     await self.ensure_open()
|   File "python3.11/site-packages/websockets/legacy/protocol.py", line 938, in ensure_open
|     raise self.connection_closed_exc()
| websockets.exceptions.ConnectionClosedOK: received 1001 (going away); then sent 1001 (going away)
| 
| The above exception was the direct cause of the following exception:
| 
| Traceback (most recent call last):
|   File "python3.11/site-packages/pycrdt_websocket/asgi_server.py", line 33, in send
|     await self._send(
|   File "python3.11/site-packages/starlette/_exception_handler.py", line 48, in sender
|     await send(message)
|   File "python3.11/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 343, in asgi_send
|     raise ClientDisconnected from exc
| uvicorn.protocols.utils.ClientDisconnected

If this is something that could be fixed in pycrdt, I'm happy to work on it!

@darabos darabos added the bug Something isn't working label Nov 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant