diff --git a/CHANGELOG.md b/CHANGELOG.md index 992dcff6..172072cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## Unreleased +- Fix generate the idle connection list. (#920) - Handle `SSLError` exception. (#918) ## 1.0.5 (March 27th, 2024) diff --git a/httpcore/_async/connection_pool.py b/httpcore/_async/connection_pool.py index 214dfc4b..da43b8dc 100644 --- a/httpcore/_async/connection_pool.py +++ b/httpcore/_async/connection_pool.py @@ -251,7 +251,13 @@ 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 len( + [ + connection + for connection in self._connections + if connection.is_idle() + ] + ) > self._max_keepalive_connections ): # log: "closing idle connection" diff --git a/httpcore/_sync/connection_pool.py b/httpcore/_sync/connection_pool.py index 01bec59e..13087c01 100644 --- a/httpcore/_sync/connection_pool.py +++ b/httpcore/_sync/connection_pool.py @@ -251,7 +251,13 @@ 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 len( + [ + connection + for connection in self._connections + if connection.is_idle() + ] + ) > 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..0dd3646d 100644 --- a/tests/_async/test_connection_pool.py +++ b/tests/_async/test_connection_pool.py @@ -830,3 +830,33 @@ async def trace(name, kwargs): "http11.response_closed.started", "http11.response_closed.complete", ] + + +@pytest.mark.anyio +async def test_connection_pool_with_idle_connections(): + """ + When the max_keepalive_connections is not set, we can get 10 idle connections after 10 requests, + if max_keepalive_connections is set to 5, we only get 5 idle connections after 10 requests. + """ + network_backend = httpcore.AsyncMockBackend( + [ + b"HTTP/1.1 200 OK\r\n", + b"Content-Type: plain/text\r\n", + b"Content-Length: 13\r\n", + b"\r\n", + b"Hello, world!", + ] + * 10 + ) + + async with httpcore.AsyncConnectionPool(network_backend=network_backend) as pool: + for i in range(10): + async with pool.stream("GET", f"https://example{i}.com/") as response: + await response.aread() + + assert 10 == len([c for c in pool.connections if c.is_idle()]) + pool._max_keepalive_connections = 5 + for i in range(10): + async with pool.stream("GET", f"https://example{i}.com/") as response: + await response.aread() + assert 5 == len([c for c in pool.connections if c.is_idle()])