Skip to content

Commit 748bfdf

Browse files
Handle ASGI lifespan (#127)
1 parent 29ac244 commit 748bfdf

File tree

2 files changed

+43
-37
lines changed

2 files changed

+43
-37
lines changed

src/pycrdt/websocket/asgi_server.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,24 @@ async def __call__(
7979
receive: Callable[[], Awaitable[dict[str, Any]]],
8080
send: Callable[[dict[str, Any]], Awaitable[None]],
8181
):
82-
msg = await receive()
83-
if msg["type"] == "websocket.connect":
84-
if self._on_connect is not None:
85-
close = self._on_connect(msg, scope)
86-
if isawaitable(close):
87-
close = await close
88-
if close:
82+
if scope["type"] == "lifespan":
83+
while True:
84+
message = await receive()
85+
if message["type"] == "lifespan.startup":
86+
await send({"type": "lifespan.startup.complete"})
87+
elif message["type"] == "lifespan.shutdown":
88+
await send({"type": "lifespan.shutdown.complete"})
8989
return
90+
elif scope["type"] == "websocket":
91+
msg = await receive()
92+
if msg["type"] == "websocket.connect":
93+
if self._on_connect is not None:
94+
close = self._on_connect(msg, scope)
95+
if isawaitable(close):
96+
close = await close
97+
if close:
98+
return
9099

91-
await send({"type": "websocket.accept"})
92-
websocket = ASGIWebsocket(receive, send, scope["path"], self._on_disconnect)
93-
await self._websocket_server.serve(websocket)
100+
await send({"type": "websocket.accept"})
101+
websocket = ASGIWebsocket(receive, send, scope["path"], self._on_disconnect)
102+
await self._websocket_server.serve(websocket)

tests/conftest.py

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -41,33 +41,30 @@ def ystore_api(request):
4141

4242
@pytest.fixture
4343
async def yws_server(request, unused_tcp_port, websocket_server_api):
44-
try:
45-
async with create_task_group() as tg:
46-
try:
47-
kwargs = request.param
48-
except AttributeError:
49-
kwargs = {}
50-
websocket_server = WebsocketServer(**kwargs)
51-
app = ASGIServer(websocket_server)
52-
config = Config()
53-
config.bind = [f"localhost:{unused_tcp_port}"]
54-
shutdown_event = Event()
55-
if websocket_server_api == "websocket_server_start_stop":
56-
websocket_server = StartStopContextManager(websocket_server, tg)
57-
if current_async_library() == "trio":
58-
from hypercorn.trio import serve
59-
else:
60-
from hypercorn.asyncio import serve
61-
async with websocket_server as websocket_server:
62-
tg.start_soon(
63-
partial(serve, app, config, shutdown_trigger=shutdown_event.wait, mode="asgi")
64-
)
65-
await ensure_server_running("localhost", unused_tcp_port)
66-
pytest.port = unused_tcp_port
67-
yield unused_tcp_port, websocket_server
68-
shutdown_event.set()
69-
except Exception:
70-
pass
44+
async with create_task_group() as tg:
45+
try:
46+
kwargs = request.param
47+
except AttributeError:
48+
kwargs = {}
49+
websocket_server = WebsocketServer(**kwargs)
50+
app = ASGIServer(websocket_server)
51+
config = Config()
52+
config.bind = [f"localhost:{unused_tcp_port}"]
53+
shutdown_event = Event()
54+
if websocket_server_api == "websocket_server_start_stop":
55+
websocket_server = StartStopContextManager(websocket_server, tg)
56+
if current_async_library() == "trio":
57+
from hypercorn.trio import serve
58+
else:
59+
from hypercorn.asyncio import serve
60+
async with websocket_server as websocket_server:
61+
tg.start_soon(
62+
partial(serve, app, config, shutdown_trigger=shutdown_event.wait, mode="asgi")
63+
)
64+
await ensure_server_running("localhost", unused_tcp_port)
65+
pytest.port = unused_tcp_port
66+
yield unused_tcp_port, websocket_server
67+
shutdown_event.set()
7168

7269

7370
@pytest.fixture

0 commit comments

Comments
 (0)