Skip to content

Commit c2a5026

Browse files
committed
connection pool is now a real pool. we no longer rely on threading.local for anything in redis-py. yaa!
1 parent 2a3e05c commit c2a5026

File tree

3 files changed

+32
-26
lines changed

3 files changed

+32
-26
lines changed

redis/client.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import datetime
2-
import threading
32
import time
43
import warnings
54
from itertools import chain, imap, islice, izip, starmap
@@ -112,7 +111,7 @@ def parse_config(response, **options):
112111
return response and pairs_to_dict(response) or {}
113112
return response == 'OK'
114113

115-
class Redis(threading.local):
114+
class Redis(object):
116115
"""
117116
Implementation of the Redis protocol.
118117

redis/connection.py

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import errno
22
import os
33
import socket
4-
import threading
5-
from itertools import imap
4+
from itertools import chain, imap
65
from redis.exceptions import ConnectionError, ResponseError, InvalidResponse
76

87
class PythonParser(object):
@@ -235,36 +234,43 @@ def _connect(self):
235234
sock.connect(self.path)
236235
return sock
237236

237+
# TODO: add ability to block waiting on a connection to be released
238238
class ConnectionPool(object):
239-
"""
240-
A connection pool that maintains only one connection. Great for
241-
single-threaded apps with no sharding
242-
"""
243-
def __init__(self, connection_class=Connection, **kwargs):
239+
"Generic connection pool"
240+
def __init__(self, connection_class=Connection, max_connections=None,
241+
**connection_kwargs):
244242
self.connection_class = connection_class
245-
self.kwargs = kwargs
246-
self._connection = None
247-
self._in_use = False
248-
249-
def copy(self):
250-
"Return a new instance of this class with the same parameters"
251-
return self.__class__(self.connection_class, **self.kwargs)
243+
self.connection_kwargs = connection_kwargs
244+
self.max_connections = max_connections or 2**31
245+
self._created_connections = 0
246+
self._available_connections = []
247+
self._in_use_connections = set()
252248

253249
def get_connection(self, command_name, *keys):
254250
"Get a connection from the pool"
255-
if self._in_use:
256-
raise ConnectionError("Connection already in-use")
257-
if not self._connection:
258-
self._connection = self.connection_class(**self.kwargs)
259-
self._in_use = True
260-
return self._connection
251+
try:
252+
connection = self._available_connections.pop()
253+
except IndexError:
254+
connection = self.make_connection()
255+
self._in_use_connections.add(connection)
256+
return connection
257+
258+
def make_connection(self):
259+
"Create a new connection"
260+
if self._created_connections >= self.max_connections:
261+
raise Exception("Too many connections")
262+
self._created_connections += 1
263+
return self.connection_class(**self.connection_kwargs)
261264

262265
def release(self, connection):
263266
"Releases the connection back to the pool"
264-
assert self._connection == connection
265-
self._in_use = False
267+
# assert self._connection == connection
268+
# self._in_use = False
269+
self._in_use_connections.remove(connection)
270+
self._available_connections.append(connection)
266271

267272
def disconnect(self):
268273
"Disconnects all connections in the pool"
269-
if self._connection:
270-
self._connection.disconnect()
274+
all_conns = chain(self._available_connections, self._in_use_connections)
275+
for connection in all_conns:
276+
connection.disconnect()

tests/connection_pool.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class ConnectionPoolTestCase(unittest.TestCase):
3232
# self.assertEquals(conns, mgr_conns)
3333

3434
def test_threaded_workers(self):
35+
# TODO: review this, does it even make sense anymore?
3536
r = redis.Redis(host='localhost', port=6379, db=9)
3637
r.set('a', 'foo')
3738
r.set('b', 'bar')

0 commit comments

Comments
 (0)