Skip to content

Commit 8907150

Browse files
committed
Don't perform blocking connect inside the BlockingConnectionQueue Condition variable.
1 parent 054caf3 commit 8907150

File tree

1 file changed

+22
-10
lines changed

1 file changed

+22
-10
lines changed

redis/asyncio/connection.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,15 +1027,8 @@ def can_get_connection(self) -> bool:
10271027
)
10281028

10291029
async def get_connection(self, command_name, *keys, **options):
1030-
"""Get a connection from the pool"""
1031-
try:
1032-
connection = self._available_connections.pop()
1033-
except IndexError:
1034-
if len(self._in_use_connections) >= self.max_connections:
1035-
raise ConnectionError("Too many connections") from None
1036-
connection = self.make_connection()
1037-
self._in_use_connections.add(connection)
1038-
1030+
"""Get a connected connection from the pool"""
1031+
connection = self.get_available_connection()
10391032
try:
10401033
await self.ensure_connection(connection)
10411034
except BaseException:
@@ -1044,6 +1037,16 @@ async def get_connection(self, command_name, *keys, **options):
10441037

10451038
return connection
10461039

1040+
def get_available_connection(self):
1041+
"""Get a connection from the pool, without making sure it is connected"""
1042+
try:
1043+
connection = self._available_connections.pop()
1044+
except IndexError:
1045+
if len(self._in_use_connections) >= self.max_connections:
1046+
raise ConnectionError("Too many connections") from None
1047+
connection = self.make_connection()
1048+
self._in_use_connections.add(connection)
1049+
10471050
def get_encoder(self):
10481051
"""Return an encoder based on encoding settings"""
10491052
kwargs = self.connection_kwargs
@@ -1169,10 +1172,19 @@ async def get_connection(self, command_name, *keys, **options):
11691172
async with async_timeout(self.timeout):
11701173
async with self._condition:
11711174
await self._condition.wait_for(self.can_get_connection)
1172-
return await super().get_connection(command_name, *keys, **options)
1175+
connection = super().get_available_connection()
1176+
11731177
except asyncio.TimeoutError as err:
11741178
raise ConnectionError("No connection available.") from err
11751179

1180+
# We now perform the connection check outside of the lock.
1181+
try:
1182+
await self.ensure_connection(connection)
1183+
return connection
1184+
except BaseException:
1185+
await self.release(connection)
1186+
raise
1187+
11761188
async def release(self, connection: AbstractConnection):
11771189
"""Releases the connection back to the pool."""
11781190
async with self._condition:

0 commit comments

Comments
 (0)