-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
Client timeout includes connection pool queue wait time #10313
Comments
I'm under the impression that is the intended design of the total timeout. i.e. It is the total time of everything. |
So all of this seems more like a bug rather than "intended design." |
It could be clearer, but it does say "for the whole operation". I think it'd probably make sense to change it to behave the way you expected though, as an overall timeout can be easily achieved with an external asyncio.timeout() call from the user. It may not be as trivial as you think to change the code though, so feel free to take a look and submit a PR if it easy enough (unless anyone else has any objections). |
"for the whole operation," in the current implementation, effectively means a timeout for a group of concurrent requests (as in the example I provided) within a single session. This contradicts the idea of being able to set a timeout for an individual request. I found an old issue #3203 where this problem is mentioned. It seems that @asvetlov acknowledges that this is confusing and plans to fix this behavior:
Perhaps I will do so, as I actively use aiohttp and don’t see an alternative for myself, but this issue causes me discomfort. I don’t want to use workarounds in user code to solve this problem, as they have their downsides, and ideally, the timeout should work as expected. Thank you for your involvement. |
I agree the current behavior causes confusion. Changing the total timeout behavior is going to be a significant breaking change as many downstream applications currently expect the request to be cancelled as soon as the total timeout is met regardless of any waits on the connection pool. If we change the behavior here it could lead to cases where the timeout wait is now orders of magnitude longer because there are no free connections. We shouldn't backport a change like that to 3.x. The unintended consequence of changing it means that we would likely see downstream code having to wrap all requests in asyncio.timeout instead of using the built-in timeout functionality. This would also mean we would need to make sure everything is cancellation safe. |
Describe the bug
The issue lies in how aiohttp handles timeouts when using ClientSession and connection pooling. Currently, the timeout starts counting from the moment the coroutine session.get() is called, not from when the connection is acquired from the connection pool. This means that the time spent waiting in the connection pool queue is also included in the timeout calculation, leading to unexpected TimeoutError exceptions even if the actual request could be completed within the specified timeout.
This behavior can cause issues when the connection pool is overloaded with many simultaneous requests, as clients experience timeouts primarily due to delays in acquiring a connection rather than delays in the actual request processing.
To Reproduce
TimeoutError
server.py
client.py
Run a server as follows:
Then run a client:
Despite setting the timeout to 5 seconds, many requests fail with TimeoutError.
The observed behavior indicates that the timeout starts before acquiring a connection from the pool, rather than only including the time for the actual request.
Expected behavior
All requests will be executed successfully without a TimeoutError.
The timeout should start counting only after a connection is acquired from the connection pool. This ensures that the specified timeout duration applies exclusively to the actual request-processing time, making the timeout behavior predictable and intuitive.
Logs/tracebacks
Python Version
3.13.0
aiohttp Version
3.11.11
multidict Version
6.1.0
propcache Version
0.2.1
yarl Version
1.18.3
OS
Debian GNU/Linux 11 (bullseye)
Related component
Client
Additional context
No response
Code of Conduct
The text was updated successfully, but these errors were encountered: