Skip to content

Commit a40f574

Browse files
committed
Add the from_pool argument to asyncio.Redis
1 parent 19b55c6 commit a40f574

File tree

4 files changed

+62
-31
lines changed

4 files changed

+62
-31
lines changed

docs/examples/asyncio_examples.ipynb

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,26 @@
4444
"await connection.close()"
4545
]
4646
},
47+
{
48+
"cell_type": "markdown",
49+
"metadata": {},
50+
"source": [
51+
"If you create custom `ConnectionPool` for the `Redis` instance to use, use the `from_pool` argument. This will cause the pool to be disconnected along with the Redis instance. Disconnecting the connection pool simply disconnects all connections hosted in the pool."
52+
]
53+
},
54+
{
55+
"cell_type": "code",
56+
"execution_count": null,
57+
"metadata": {},
58+
"outputs": [],
59+
"source": [
60+
"import redis.asyncio as redis\n",
61+
"\n",
62+
"pool = redis.ConnectionPool.from_url(\"redis://localhost\")\n",
63+
"connection = redis.Redis(from_pool=pool)\n",
64+
"await connection.close()"
65+
]
66+
},
4767
{
4868
"cell_type": "markdown",
4969
"metadata": {
@@ -53,7 +73,8 @@
5373
}
5474
},
5575
"source": [
56-
"If you supply a custom `ConnectionPool` that is supplied to several `Redis` instances, you may want to disconnect the connection pool explicitly. Disconnecting the connection pool simply disconnects all connections hosted in the pool."
76+
"\n",
77+
"However, If you supply a `ConnectionPool` that is shared several `Redis` instances, you may want to disconnect the connection pool explicitly. use the `connection_pool` argument in that case."
5778
]
5879
},
5980
{
@@ -69,10 +90,12 @@
6990
"source": [
7091
"import redis.asyncio as redis\n",
7192
"\n",
72-
"connection = redis.Redis(auto_close_connection_pool=False)\n",
73-
"await connection.close()\n",
74-
"# Or: await connection.close(close_connection_pool=False)\n",
75-
"await connection.connection_pool.disconnect()"
93+
"pool = redis.ConnectionPool.from_url(\"redis://localhost\")\n",
94+
"connection1 = redis.Redis(connection_pool=pool)\n",
95+
"connection2 = redis.Redis(connection_pool=pool)\n",
96+
"await connection1.close()\n",
97+
"await connection2.close()\n",
98+
"await pool.disconnect()"
7699
]
77100
},
78101
{

redis/asyncio/client.py

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ def from_url(
114114
cls,
115115
url: str,
116116
single_connection_client: bool = False,
117-
auto_close_connection_pool: bool = True,
118117
**kwargs,
119118
):
120119
"""
@@ -160,12 +159,10 @@ class initializer. In the case of conflicting arguments, querystring
160159
161160
"""
162161
connection_pool = ConnectionPool.from_url(url, **kwargs)
163-
redis = cls(
164-
connection_pool=connection_pool,
162+
return cls(
163+
from_pool=connection_pool,
165164
single_connection_client=single_connection_client,
166165
)
167-
redis.auto_close_connection_pool = auto_close_connection_pool
168-
return redis
169166

170167
def __init__(
171168
self,
@@ -179,6 +176,7 @@ def __init__(
179176
socket_keepalive: Optional[bool] = None,
180177
socket_keepalive_options: Optional[Mapping[int, Union[int, bytes]]] = None,
181178
connection_pool: Optional[ConnectionPool] = None,
179+
from_pool: Optional[ConnectionPool] = None,
182180
unix_socket_path: Optional[str] = None,
183181
encoding: str = "utf-8",
184182
encoding_errors: str = "strict",
@@ -200,6 +198,7 @@ def __init__(
200198
lib_version: Optional[str] = get_lib_version(),
201199
username: Optional[str] = None,
202200
retry: Optional[Retry] = None,
201+
# deprecated. create a pool and use connection_pool instead
203202
auto_close_connection_pool: bool = True,
204203
redis_connect_func=None,
205204
credential_provider: Optional[CredentialProvider] = None,
@@ -213,14 +212,9 @@ def __init__(
213212
To retry on TimeoutError, `retry_on_timeout` can also be set to `True`.
214213
"""
215214
kwargs: Dict[str, Any]
216-
# auto_close_connection_pool only has an effect if connection_pool is
217-
# None. This is a similar feature to the missing __del__ to resolve #1103,
218-
# but it accounts for whether a user wants to manually close the connection
219-
# pool, as a similar feature to ConnectionPool's __del__.
220-
self.auto_close_connection_pool = (
221-
auto_close_connection_pool if connection_pool is None else False
222-
)
223-
if not connection_pool:
215+
216+
if not connection_pool and not from_pool:
217+
# Create internal connection pool, expected to be closed by Redis instance
224218
if not retry_on_error:
225219
retry_on_error = []
226220
if retry_on_timeout is True:
@@ -277,8 +271,28 @@ def __init__(
277271
"ssl_check_hostname": ssl_check_hostname,
278272
}
279273
)
280-
connection_pool = ConnectionPool(**kwargs)
281-
self.connection_pool = connection_pool
274+
# backwards compatibility. This arg only used if no pool
275+
# is provided
276+
if auto_close_connection_pool:
277+
from_pool = ConnectionPool(**kwargs)
278+
else:
279+
connection_pool = ConnectionPool(**kwargs)
280+
281+
if from_pool is not None:
282+
# internal connection pool, expected to be closed by Redis instance
283+
if connection_pool is not None:
284+
raise ValueError(
285+
"Cannot use both from_pool and connection_pool arguments"
286+
)
287+
self.connection_pool = from_pool
288+
self.auto_close_connection_pool = True # the Redis instance closes the pool
289+
else:
290+
# external connection pool, expected to be closed by caller
291+
self.connection_pool = connection_pool
292+
self.auto_close_connection_pool = (
293+
False # the user is expected to close the pool
294+
)
295+
282296
self.single_connection_client = single_connection_client
283297
self.connection: Optional[Connection] = None
284298

redis/asyncio/connection.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1199,7 +1199,7 @@ class BlockingConnectionPool(ConnectionPool):
11991199
Thread-safe blocking connection pool::
12001200
12011201
>>> from redis.client import Redis
1202-
>>> client = Redis(connection_pool=BlockingConnectionPool())
1202+
>>> client = Redis(from_pool=BlockingConnectionPool())
12031203
12041204
It performs the same function as the default
12051205
:py:class:`~redis.ConnectionPool` implementation, in that,

redis/asyncio/sentinel.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -338,12 +338,9 @@ def master_for(
338338

339339
connection_pool = connection_pool_class(service_name, self, **connection_kwargs)
340340
# The Redis object "owns" the pool
341-
auto_close_connection_pool = True
342-
client = redis_class(
343-
connection_pool=connection_pool,
341+
return redis_class(
342+
from_pool=connection_pool,
344343
)
345-
client.auto_close_connection_pool = auto_close_connection_pool
346-
return client
347344

348345
def slave_for(
349346
self,
@@ -375,9 +372,6 @@ def slave_for(
375372

376373
connection_pool = connection_pool_class(service_name, self, **connection_kwargs)
377374
# The Redis object "owns" the pool
378-
auto_close_connection_pool = True
379-
client = redis_class(
380-
connection_pool=connection_pool,
375+
return redis_class(
376+
from_pool=connection_pool,
381377
)
382-
client.auto_close_connection_pool = auto_close_connection_pool
383-
return client

0 commit comments

Comments
 (0)