7
7
from __future__ import annotations
8
8
9
9
import asyncio
10
+ import typing
10
11
from collections .abc import Awaitable , Callable
11
12
import functools
12
13
import inspect
@@ -341,7 +342,7 @@ class Pool:
341
342
'_queue' , '_loop' , '_minsize' , '_maxsize' ,
342
343
'_init' , '_connect' , '_reset' , '_connect_args' , '_connect_kwargs' ,
343
344
'_holders' , '_initialized' , '_initializing' , '_closing' ,
344
- '_closed' , '_connection_class' , '_record_class' , '_generation' ,
345
+ '_closed' , '_connection_class' , '_connection_holder_class' , ' _record_class' , '_generation' ,
345
346
'_setup' , '_max_queries' , '_max_inactive_connection_lifetime'
346
347
)
347
348
@@ -356,6 +357,7 @@ def __init__(self, *connect_args,
356
357
reset = None ,
357
358
loop ,
358
359
connection_class ,
360
+ connection_holder_class : typing .Type [PoolConnectionHolder ] = PoolConnectionHolder ,
359
361
record_class ,
360
362
** connect_kwargs ):
361
363
@@ -408,6 +410,7 @@ def __init__(self, *connect_args,
408
410
self ._queue = None
409
411
410
412
self ._connection_class = connection_class
413
+ self ._connection_holder_class = connection_holder_class
411
414
self ._record_class = record_class
412
415
413
416
self ._closing = False
@@ -443,37 +446,48 @@ async def _async__init__(self):
443
446
self ._initialized = True
444
447
445
448
async def _initialize (self ):
449
+ self ._initialize_connections_queue ()
450
+ if self ._minsize :
451
+ await self ._initialize_connections ()
452
+
453
+ def _initialize_connections_queue (self ) -> None :
446
454
self ._queue = asyncio .LifoQueue (maxsize = self ._maxsize )
447
455
for _ in range (self ._maxsize ):
448
- ch = PoolConnectionHolder (
449
- self ,
456
+ ch = self ._connection_holder_class (
457
+ pool = self ,
458
+ setup = self ._setup ,
450
459
max_queries = self ._max_queries ,
451
460
max_inactive_time = self ._max_inactive_connection_lifetime ,
452
- setup = self ._setup )
453
-
461
+ )
454
462
self ._holders .append (ch )
455
463
self ._queue .put_nowait (ch )
456
464
457
- if self ._minsize :
458
- # Since we use a LIFO queue, the first items in the queue will be
459
- # the last ones in `self._holders`. We want to pre-connect the
460
- # first few connections in the queue, therefore we want to walk
461
- # `self._holders` in reverse.
462
-
463
- # Connect the first connection holder in the queue so that
464
- # any connection issues are visible early.
465
- first_ch = self ._holders [- 1 ] # type: PoolConnectionHolder
466
- await first_ch .connect ()
467
-
468
- if self ._minsize > 1 :
469
- connect_tasks = []
470
- for i , ch in enumerate (reversed (self ._holders [:- 1 ])):
471
- # `minsize - 1` because we already have first_ch
472
- if i >= self ._minsize - 1 :
473
- break
474
- connect_tasks .append (ch .connect ())
475
-
476
- await asyncio .gather (* connect_tasks )
465
+
466
+ async def _initialize_connections (self ) -> None :
467
+
468
+ if not self ._minsize :
469
+ raise exceptions .InterfaceError (
470
+ 'pool is already initialized with min_size > 0' )
471
+
472
+ # Since we use a LIFO queue, the first items in the queue will be
473
+ # the last ones in `self._holders`. We want to pre-connect the
474
+ # first few connections in the queue, therefore we want to walk
475
+ # `self._holders` in reverse.
476
+
477
+ # Connect the first connection holder in the queue so that
478
+ # any connection issues are visible early.
479
+ first_ch = self ._holders [- 1 ] # type: PoolConnectionHolder
480
+ await first_ch .connect ()
481
+
482
+ if self ._minsize > 1 :
483
+ connect_tasks = []
484
+ for i , ch in enumerate (reversed (self ._holders [:- 1 ])):
485
+ # `minsize - 1` because we already have first_ch
486
+ if i >= self ._minsize - 1 :
487
+ break
488
+ connect_tasks .append (ch .connect ())
489
+
490
+ await asyncio .gather (* connect_tasks )
477
491
478
492
def is_closing (self ):
479
493
"""Return ``True`` if the pool is closing or is closed.
@@ -1083,6 +1097,7 @@ def create_pool(dsn=None, *,
1083
1097
reset = None ,
1084
1098
loop = None ,
1085
1099
connection_class = connection .Connection ,
1100
+ connection_holder_class : typing .Type [PoolConnectionHolder ] = PoolConnectionHolder ,
1086
1101
record_class = protocol .Record ,
1087
1102
** connect_kwargs ):
1088
1103
r"""Create a connection pool.
@@ -1142,6 +1157,11 @@ def create_pool(dsn=None, *,
1142
1157
The class to use for connections. Must be a subclass of
1143
1158
:class:`~asyncpg.connection.Connection`.
1144
1159
1160
+ :param PoolConnectionHolder connection_holder_class:
1161
+ The class to use for connection holders. This class is used
1162
+ to manage the connection lifecycle in the pool. Must be a subclass of
1163
+ :class:`~asyncpg.pool.PoolConnectionHolder`
1164
+
1145
1165
:param type record_class:
1146
1166
If specified, the class to use for records returned by queries on
1147
1167
the connections in this pool. Must be a subclass of
@@ -1230,10 +1250,14 @@ def create_pool(dsn=None, *,
1230
1250
1231
1251
.. versionchanged:: 0.30.0
1232
1252
Added the *connect* and *reset* parameters.
1253
+
1254
+ .. versionchanged:: 0.31.0
1255
+ Added the *pool_connection_holder_class* parameter.
1233
1256
"""
1234
1257
return Pool (
1235
1258
dsn ,
1236
1259
connection_class = connection_class ,
1260
+ connection_holder_class = connection_holder_class ,
1237
1261
record_class = record_class ,
1238
1262
min_size = min_size ,
1239
1263
max_size = max_size ,
0 commit comments