Skip to content

Commit 9997cae

Browse files
authored
Create a task per request handling (#3442)
It makes a separate context vars copy for every web-handler run
1 parent 8103b8c commit 9997cae

File tree

3 files changed

+17
-11
lines changed

3 files changed

+17
-11
lines changed

‎CHANGES/3406.feature‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Create a task per request handling.

‎aiohttp/web_protocol.py‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,10 @@ async def start(self) -> None:
400400
message, payload, self, writer, handler)
401401
try:
402402
try:
403-
resp = await self._request_handler(request)
403+
# a new task is used for copy context vars (#3406)
404+
task = self._loop.create_task(
405+
self._request_handler(request))
406+
resp = await task
404407
except HTTPException as exc:
405408
resp = exc
406409
except asyncio.CancelledError:

‎tests/test_web_protocol.py‎

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ async def test_simple(srv, buf) -> None:
237237
srv.data_received(
238238
b'GET / HTTP/1.1\r\n\r\n')
239239

240-
await asyncio.sleep(0)
240+
await asyncio.sleep(0.05)
241241
assert buf.startswith(b'HTTP/1.1 200 OK\r\n')
242242

243243

@@ -450,7 +450,7 @@ async def handle_request(request):
450450
b'Content-Length: 50\r\n\r\n')
451451
await asyncio.sleep(0)
452452
assert not transport.close.called
453-
await asyncio.sleep(0)
453+
await asyncio.sleep(0.05)
454454
transport.close.assert_called_with()
455455

456456

@@ -465,7 +465,7 @@ async def handle_request(request):
465465
srv.connection_made(transport)
466466
request_handler.side_effect = handle_request
467467

468-
await asyncio.sleep(0)
468+
await asyncio.sleep(0.05)
469469
assert not transport.close.called
470470

471471
srv.data_received(
@@ -475,7 +475,7 @@ async def handle_request(request):
475475
await asyncio.sleep(0)
476476
assert not transport.close.called
477477

478-
await asyncio.sleep(0)
478+
await asyncio.sleep(0.05)
479479
transport.close.assert_called_with()
480480

481481

@@ -490,7 +490,7 @@ async def test_handle_payload_access_error(
490490
b'some data'
491491
)
492492
# start request_handler task
493-
await asyncio.sleep(0)
493+
await asyncio.sleep(0.05)
494494

495495
with pytest.raises(web.PayloadAccessError):
496496
await request_handler.call_args[0][0].content.read()
@@ -582,9 +582,10 @@ async def test_keep_alive(make_srv, transport, ceil) -> None:
582582
b'Host: example.com\r\n'
583583
b'Content-Length: 0\r\n\r\n')
584584

585-
await asyncio.sleep(0)
586-
waiter = srv._waiter
587-
assert waiter
585+
waiter = None
586+
while waiter is None:
587+
await asyncio.sleep(0)
588+
waiter = srv._waiter
588589
assert srv._keepalive_handle is not None
589590
assert not transport.close.called
590591

@@ -681,7 +682,7 @@ async def test_close(srv, transport) -> None:
681682
b'Host: example.com\r\n'
682683
b'Content-Length: 0\r\n\r\n')
683684

684-
await asyncio.sleep(0)
685+
await asyncio.sleep(0.05)
685686
assert srv._task_handler
686687
assert srv._waiter
687688

@@ -721,7 +722,7 @@ async def handle(request):
721722
assert len(srv._messages) == 2
722723
assert srv._waiter is not None
723724

724-
await asyncio.sleep(0)
725+
await asyncio.sleep(0.05)
725726
assert srv._task_handler is not None
726727
assert srv._waiter is not None
727728
assert processed == 2
@@ -856,3 +857,4 @@ async def test_two_data_received_without_waking_up_start_task(srv) -> None:
856857

857858
assert len(srv._messages) == 2
858859
assert srv._waiter.done()
860+
await asyncio.sleep(0.01)

0 commit comments

Comments
 (0)