11import ssl
22import sys
33from types import TracebackType
4- from typing import AsyncIterable , AsyncIterator , Iterable , List , Optional , Type
4+ from typing import (
5+ AsyncIterable ,
6+ AsyncIterator ,
7+ Iterable ,
8+ Iterator ,
9+ List ,
10+ Optional ,
11+ Type ,
12+ )
513
614from .._backends .auto import AutoBackend
715from .._backends .base import SOCKET_OPTION , AsyncNetworkBackend
@@ -238,6 +246,7 @@ def _assign_requests_to_connections(self) -> List[AsyncConnectionInterface]:
238246 those connections to be handled seperately.
239247 """
240248 closing_connections = []
249+ idling_count = 0
241250
242251 # First we handle cleaning up any connections that are closed,
243252 # have expired their keep-alive, or surplus idle connections.
@@ -249,52 +258,53 @@ def _assign_requests_to_connections(self) -> List[AsyncConnectionInterface]:
249258 # log: "closing expired connection"
250259 self ._connections .remove (connection )
251260 closing_connections .append (connection )
252- elif (
253- connection .is_idle ()
254- and len ([connection .is_idle () for connection in self ._connections ])
255- > self ._max_keepalive_connections
256- ):
261+ elif connection .is_idle ():
262+ if idling_count < self ._max_keepalive_connections :
263+ idling_count += 1
264+ continue
257265 # log: "closing idle connection"
258266 self ._connections .remove (connection )
259267 closing_connections .append (connection )
260268
261269 # Assign queued requests to connections.
262- queued_requests = [request for request in self ._requests if request .is_queued ()]
263- for pool_request in queued_requests :
270+ for pool_request in list (self ._requests ):
271+ if not pool_request .is_queued ():
272+ continue
273+
264274 origin = pool_request .request .url .origin
265- available_connections = [
275+ available_connections_iter : Iterator [ AsyncConnectionInterface ] = (
266276 connection
267277 for connection in self ._connections
268278 if connection .can_handle_request (origin ) and connection .is_available ()
269- ]
270- idle_connections = [
271- connection for connection in self ._connections if connection .is_idle ()
272- ]
279+ )
280+ available_connection = next (available_connections_iter , None )
273281
274282 # There are three cases for how we may be able to handle the request:
275283 #
276284 # 1. There is an existing connection that can handle the request.
277285 # 2. We can create a new connection to handle the request.
278286 # 3. We can close an idle connection and then create a new connection
279287 # to handle the request.
280- if available_connections :
288+ if available_connection is not None :
281289 # log: "reusing existing connection"
282- connection = available_connections [0 ]
283- pool_request .assign_to_connection (connection )
290+ pool_request .assign_to_connection (available_connection )
284291 elif len (self ._connections ) < self ._max_connections :
285292 # log: "creating new connection"
286293 connection = self .create_connection (origin )
287294 self ._connections .append (connection )
288295 pool_request .assign_to_connection (connection )
289- elif idle_connections :
290- # log: "closing idle connection"
291- connection = idle_connections [0 ]
292- self ._connections .remove (connection )
293- closing_connections .append (connection )
294- # log: "creating new connection"
295- connection = self .create_connection (origin )
296- self ._connections .append (connection )
297- pool_request .assign_to_connection (connection )
296+ else :
297+ idling_connection = next (
298+ (c for c in self ._connections if c .is_idle ()), None
299+ )
300+ if idling_connection is not None :
301+ # log: "closing idle connection"
302+ self ._connections .remove (idling_connection )
303+ closing_connections .append (idling_connection )
304+ # log: "creating new connection"
305+ new_connection = self .create_connection (origin )
306+ self ._connections .append (new_connection )
307+ pool_request .assign_to_connection (new_connection )
298308
299309 return closing_connections
300310
0 commit comments