diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b46c6c0..a348ab84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## Unreleased + +- Fix `max_keepalive_connections` not being properly handled. (#1000) + ## Version 1.0.7 (November 15th, 2024) - Support `proxy=…` configuration on `ConnectionPool()`. (#974) diff --git a/httpcore/_async/connection_pool.py b/httpcore/_async/connection_pool.py index 96e973d0..5ef74e64 100644 --- a/httpcore/_async/connection_pool.py +++ b/httpcore/_async/connection_pool.py @@ -291,7 +291,7 @@ def _assign_requests_to_connections(self) -> list[AsyncConnectionInterface]: closing_connections.append(connection) elif ( connection.is_idle() - and len([connection.is_idle() for connection in self._connections]) + and sum(connection.is_idle() for connection in self._connections) > self._max_keepalive_connections ): # log: "closing idle connection" diff --git a/httpcore/_sync/connection_pool.py b/httpcore/_sync/connection_pool.py index 9ccfa53e..4b26f9c6 100644 --- a/httpcore/_sync/connection_pool.py +++ b/httpcore/_sync/connection_pool.py @@ -291,7 +291,7 @@ def _assign_requests_to_connections(self) -> list[ConnectionInterface]: closing_connections.append(connection) elif ( connection.is_idle() - and len([connection.is_idle() for connection in self._connections]) + and sum(connection.is_idle() for connection in self._connections) > self._max_keepalive_connections ): # log: "closing idle connection" diff --git a/tests/_async/test_connection_pool.py b/tests/_async/test_connection_pool.py index 2fc27204..bc4b251e 100644 --- a/tests/_async/test_connection_pool.py +++ b/tests/_async/test_connection_pool.py @@ -30,7 +30,7 @@ async def test_connection_pool_with_keepalive(): ) async with httpcore.AsyncConnectionPool( - network_backend=network_backend, + network_backend=network_backend, max_keepalive_connections=1 ) as pool: # Sending an intial request, which once complete will return to the pool, IDLE. async with pool.stream("GET", "https://example.com/") as response: @@ -79,28 +79,33 @@ async def test_connection_pool_with_keepalive(): ) # Sending a request to a different origin will not reuse the existing IDLE connection. - async with pool.stream("GET", "http://example.com/") as response: + async with pool.stream("GET", "http://example.com/") as response_1, pool.stream( + "GET", "http://example.com/" + ) as response_2: info = [repr(c) for c in pool.connections] assert info == [ "", "", + "", ] assert ( repr(pool) - == "" + == "" ) - await response.aread() + await response_1.aread() + await response_2.aread() - assert response.status == 200 - assert response.content == b"Hello, world!" + assert response_1.status == 200 + assert response_1.content == b"Hello, world!" + assert response_2.status == 200 + assert response_2.content == b"Hello, world!" info = [repr(c) for c in pool.connections] assert info == [ - "", "", ] assert ( repr(pool) - == "" + == "" ) diff --git a/tests/_sync/test_connection_pool.py b/tests/_sync/test_connection_pool.py index ee303e5c..7adc3f5c 100644 --- a/tests/_sync/test_connection_pool.py +++ b/tests/_sync/test_connection_pool.py @@ -30,7 +30,7 @@ def test_connection_pool_with_keepalive(): ) with httpcore.ConnectionPool( - network_backend=network_backend, + network_backend=network_backend, max_keepalive_connections=1 ) as pool: # Sending an intial request, which once complete will return to the pool, IDLE. with pool.stream("GET", "https://example.com/") as response: @@ -79,28 +79,33 @@ def test_connection_pool_with_keepalive(): ) # Sending a request to a different origin will not reuse the existing IDLE connection. - with pool.stream("GET", "http://example.com/") as response: + with pool.stream("GET", "http://example.com/") as response_1, pool.stream( + "GET", "http://example.com/" + ) as response_2: info = [repr(c) for c in pool.connections] assert info == [ "", "", + "", ] assert ( repr(pool) - == "" + == "" ) - response.read() + response_1.read() + response_2.read() - assert response.status == 200 - assert response.content == b"Hello, world!" + assert response_1.status == 200 + assert response_1.content == b"Hello, world!" + assert response_2.status == 200 + assert response_2.content == b"Hello, world!" info = [repr(c) for c in pool.connections] assert info == [ - "", "", ] assert ( repr(pool) - == "" + == "" )