Skip to content

Commit 32a5840

Browse files
committed
Tune the locking in ConnectionPool.get_connection
The lock does not need to be held while waiting for the socket to establish and validate the TCP connection.
1 parent fa37b8b commit 32a5840

File tree

2 files changed

+26
-21
lines changed

2 files changed

+26
-21
lines changed

CHANGES

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
* 3.5.2 (May 14, 2020)
2+
* Tune the locking in ConnectionPool.get_connection so that the lock is
3+
not held while waiting for the socket to establish and validate the
4+
TCP connection.
15
* 3.5.1 (May 9, 2020)
26
* Fix for HSET argument validation to allow any non-None key. Thanks
37
@AleksMat, #1337, #1341

redis/connection.py

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,7 @@ def __repr__(self):
10981098
)
10991099

11001100
def reset(self):
1101-
self._lock = threading.RLock()
1101+
self._lock = threading.Lock()
11021102
self._created_connections = 0
11031103
self._available_connections = []
11041104
self._in_use_connections = set()
@@ -1177,28 +1177,29 @@ def get_connection(self, command_name, *keys, **options):
11771177
except IndexError:
11781178
connection = self.make_connection()
11791179
self._in_use_connections.add(connection)
1180+
1181+
try:
1182+
# ensure this connection is connected to Redis
1183+
connection.connect()
1184+
# connections that the pool provides should be ready to send
1185+
# a command. if not, the connection was either returned to the
1186+
# pool before all data has been read or the socket has been
1187+
# closed. either way, reconnect and verify everything is good.
11801188
try:
1181-
# ensure this connection is connected to Redis
1189+
if connection.can_read():
1190+
raise ConnectionError('Connection has data')
1191+
except ConnectionError:
1192+
connection.disconnect()
11821193
connection.connect()
1183-
# connections that the pool provides should be ready to send
1184-
# a command. if not, the connection was either returned to the
1185-
# pool before all data has been read or the socket has been
1186-
# closed. either way, reconnect and verify everything is good.
1187-
try:
1188-
if connection.can_read():
1189-
raise ConnectionError('Connection has data')
1190-
except ConnectionError:
1191-
connection.disconnect()
1192-
connection.connect()
1193-
if connection.can_read():
1194-
raise ConnectionError('Connection not ready')
1195-
except BaseException:
1196-
# release the connection back to the pool so that we don't
1197-
# leak it
1198-
self.release(connection)
1199-
raise
1200-
1201-
return connection
1194+
if connection.can_read():
1195+
raise ConnectionError('Connection not ready')
1196+
except BaseException:
1197+
# release the connection back to the pool so that we don't
1198+
# leak it
1199+
self.release(connection)
1200+
raise
1201+
1202+
return connection
12021203

12031204
def get_encoder(self):
12041205
"Return an encoder based on encoding settings"

0 commit comments

Comments
 (0)