Fix ConnectionPool state after async cancellation #986
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
The PR fixes
ConnectionPool
state after exceptions/async cancellations.Root cause analysis
ConnectionPool
removes only connections which are:At the same time, some implementations of
AsyncConnectionInterface
, e.g.AsyncHTTPConnection
don't make actual connection on construction, but are left in semi-valid state with_connection = None
. Thus,is_closed()
/is_idle
/has_expired()
returnFalse
before actual connection is established or failed during the call toAsyncHTTPConnection.handle_async_request
.Let's take a look at
ConnectionPool.handle_async_request
method:Please, pay attention, that if the request task is being cancelled between
[POINT 1]
and[POINT 2]
, the Schrödinger connection (that is neither opened, nor closed) stays in the pool forever. In the long run (that depends on the load and pool max size), all new requests are refused by the pool, raisingPoolTimeout
for any request.Please, see the
test_connection_pool_cancellation_during_waiting_for_connection()
for a reproducible example.Solution
Introduce new method of
AsyncConnectionInterface
-is_connected()
. It's not justnot is_closed()
, but returnsFalse
for such semi-constructed connections, allowing theConnectionPool
to collect them.Checklist