Skip to content

Commit

Permalink
Avoid creating a future on every websocket receive
Browse files Browse the repository at this point in the history
Only create a future on close if we need to wait
for the receive to finish
  • Loading branch information
bdraco committed Jul 14, 2024
1 parent c086795 commit 558bfcc
Showing 1 changed file with 11 additions and 8 deletions.
19 changes: 11 additions & 8 deletions aiohttp/web_ws.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class WebSocketResponse(StreamResponse):
"_close_code",
"_loop",
"_waiting",
"_close_wait",
"_exception",
"_timeout",
"_receive_timeout",
Expand Down Expand Up @@ -103,7 +104,8 @@ def __init__(
self._conn_lost = 0
self._close_code: Optional[int] = None
self._loop: Optional[asyncio.AbstractEventLoop] = None
self._waiting: Optional[asyncio.Future[bool]] = None
self._waiting: bool = False
self._close_wait: Optional[asyncio.Future[bool]] = None
self._exception: Optional[BaseException] = None
self._timeout = timeout
self._receive_timeout = receive_timeout
Expand Down Expand Up @@ -398,9 +400,10 @@ async def close(

# we need to break `receive()` cycle first,
# `close()` may be called from different task
if self._waiting is not None and not self._closed:
if self._waiting and not self._closed:
self._close_wait = self._loop.create_future()
reader.feed_data(WS_CLOSING_MESSAGE)
await self._waiting
await self._close_wait

Check notice

Code scanning / CodeQL

Statement has no effect Note

This statement has no effect.

if self._closed:
return False
Expand Down Expand Up @@ -467,7 +470,7 @@ async def receive(self, timeout: Optional[float] = None) -> WSMessage:
loop = self._loop
assert loop is not None
while True:
if self._waiting is not None:
if self._waiting:
raise RuntimeError("Concurrent call to receive() is not allowed")

if self._closed:
Expand All @@ -479,15 +482,15 @@ async def receive(self, timeout: Optional[float] = None) -> WSMessage:
return WS_CLOSING_MESSAGE

try:
self._waiting = loop.create_future()
self._waiting = True
try:
async with async_timeout.timeout(timeout or self._receive_timeout):
msg = await self._reader.read()
self._reset_heartbeat()
finally:
waiter = self._waiting
set_result(waiter, True)
self._waiting = None
self._waiting = False
if close_wait := self._close_wait:
set_result(close_wait, True)
except asyncio.TimeoutError:
raise
except EofStream:
Expand Down

0 comments on commit 558bfcc

Please sign in to comment.