summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/pool.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2006-10-24 21:32:13 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2006-10-24 21:32:13 +0000
commit6e565f723149965911d899a753aaf35b07273071 (patch)
treec8c6d3f7622a2b01a69bda8d9e603cb7cff08d1e /lib/sqlalchemy/pool.py
parent2b2385ff827680f1c081bb8e69155a99a7684d16 (diff)
downloadsqlalchemy-6e565f723149965911d899a753aaf35b07273071.tar.gz
- some new Pool utility classes, updated docs
- "use_threadlocal" on Pool defaults to False (same as create_engine)
Diffstat (limited to 'lib/sqlalchemy/pool.py')
-rw-r--r--lib/sqlalchemy/pool.py167
1 files changed, 129 insertions, 38 deletions
diff --git a/lib/sqlalchemy/pool.py b/lib/sqlalchemy/pool.py
index 047469ee6..79fc22927 100644
--- a/lib/sqlalchemy/pool.py
+++ b/lib/sqlalchemy/pool.py
@@ -28,45 +28,21 @@ proxies = {}
def manage(module, **params):
"""given a DBAPI2 module and pool management parameters, returns a proxy for the module
- that will automatically pool connections. Options are delivered to an underlying DBProxy
- object.
+ that will automatically pool connections, creating new connection pools for each
+ distinct set of connection arguments sent to the decorated module's connect() function.
Arguments:
module : a DBAPI2 database module.
-
- Options:
- echo=False : if set to True, connections being pulled and retrieved from/to the pool will
- be logged to the standard output, as well as pool sizing information.
-
- use_threadlocal=True : if set to True, repeated calls to connect() within the same
- application thread will be guaranteed to return the same connection object, if one has
- already been retrieved from the pool and has not been returned yet. This allows code to
- retrieve a connection from the pool, and then while still holding on to that connection,
- to call other functions which also ask the pool for a connection of the same arguments;
- those functions will act upon the same connection that the calling method is using.
-
- poolclass=QueuePool : the default class used by the pool module to provide pooling.
- QueuePool uses the Python Queue.Queue class to maintain a list of available connections.
- pool_size=5 : used by QueuePool - the size of the pool to be maintained. This is the
- largest number of connections that will be kept persistently in the pool. Note that the
- pool begins with no connections; once this number of connections is requested, that
- number of connections will remain.
-
- max_overflow=10 : the maximum overflow size of the pool. When the number of checked-out
- connections reaches the size set in pool_size, additional connections will be returned up
- to this limit. When those additional connections are returned to the pool, they are
- disconnected and discarded. It follows then that the total number of simultaneous
- connections the pool will allow is pool_size + max_overflow, and the total number of
- "sleeping" connections the pool will allow is pool_size. max_overflow can be set to -1 to
- indicate no overflow limit; no limit will be placed on the total number of concurrent
- connections.
+ poolclass=QueuePool : the class used by the pool module to provide pooling.
+ Options:
+ See Pool for options.
"""
try:
return proxies[module]
except KeyError:
- return proxies.setdefault(module, DBProxy(module, **params))
+ return proxies.setdefault(module, _DBProxy(module, **params))
def clear_managers():
"""removes all current DBAPI2 managers. all pools and connections are disposed."""
@@ -75,7 +51,49 @@ def clear_managers():
proxies.clear()
class Pool(object):
- def __init__(self, creator, recycle=-1, echo=None, use_threadlocal = True, auto_close_cursors=True, disallow_open_cursors=False):
+ """Base Pool class. This is an abstract class, which is implemented by various subclasses
+ including:
+
+ QueuePool - pools multiple connections using Queue.Queue
+
+ SingletonThreadPool - stores a single connection per execution thread
+
+ NullPool - doesnt do any pooling; opens and closes connections
+
+ AssertionPool - stores only one connection, and asserts that only one connection is checked out at a time.
+
+ the main argument, "creator", is a callable function that returns a newly connected DBAPI connection
+ object.
+
+ Options that are understood by Pool are:
+
+ echo=False : if set to True, connections being pulled and retrieved from/to the pool will
+ be logged to the standard output, as well as pool sizing information. Echoing can also
+ be achieved by enabling logging for the "sqlalchemy.pool" namespace.
+
+ use_threadlocal=True : if set to True, repeated calls to connect() within the same
+ application thread will be guaranteed to return the same connection object, if one has
+ already been retrieved from the pool and has not been returned yet. This allows code to
+ retrieve a connection from the pool, and then while still holding on to that connection,
+ to call other functions which also ask the pool for a connection of the same arguments;
+ those functions will act upon the same connection that the calling method is using.
+
+ recycle=-1 : if set to non -1, a number of seconds between connection recycling, which
+ means upon checkout, if this timeout is surpassed the connection will be closed and replaced
+ with a newly opened connection.
+
+ auto_close_cursors = True : cursors, returned by connection.cursor(), are tracked and are
+ automatically closed when the connection is returned to the pool. some DBAPIs like MySQLDB
+ become unstable if cursors remain open.
+
+ disallow_open_cursors = False : if auto_close_cursors is False, and disallow_open_cursors is True,
+ will raise an exception if an open cursor is detected upon connection checkin.
+
+ If auto_close_cursors and disallow_open_cursors are both False, then no cursor processing
+ occurs upon checkin.
+
+ """
+ def __init__(self, creator, recycle=-1, echo=None, use_threadlocal=False, auto_close_cursors=True, disallow_open_cursors=False):
self.logger = logging.instance_logger(self)
self._threadconns = weakref.WeakValueDictionary()
self._creator = creator
@@ -245,8 +263,15 @@ class _CursorFairy(object):
return getattr(self.cursor, key)
class SingletonThreadPool(Pool):
- """Maintains one connection per each thread, never moving to another thread. this is
- used for SQLite."""
+ """Maintains one connection per each thread, never moving a connection to a thread
+ other than the one which it was created in.
+
+ this is used for SQLite, which both does not handle multithreading by default,
+ and also requires a singleton connection if a :memory: database is being used.
+
+ options are the same as those of Pool, as well as:
+
+ pool_size=5 - the number of threads in which to maintain connections at once."""
def __init__(self, creator, pool_size=5, **params):
Pool.__init__(self, creator, **params)
self._conns = {}
@@ -293,7 +318,26 @@ class SingletonThreadPool(Pool):
return c
class QueuePool(Pool):
- """uses Queue.Queue to maintain a fixed-size list of connections."""
+ """uses Queue.Queue to maintain a fixed-size list of connections.
+
+ Arguments include all those used by the base Pool class, as well as:
+
+ pool_size=5 : the size of the pool to be maintained. This is the
+ largest number of connections that will be kept persistently in the pool. Note that the
+ pool begins with no connections; once this number of connections is requested, that
+ number of connections will remain.
+
+ max_overflow=10 : the maximum overflow size of the pool. When the number of checked-out
+ connections reaches the size set in pool_size, additional connections will be returned up
+ to this limit. When those additional connections are returned to the pool, they are
+ disconnected and discarded. It follows then that the total number of simultaneous
+ connections the pool will allow is pool_size + max_overflow, and the total number of
+ "sleeping" connections the pool will allow is pool_size. max_overflow can be set to -1 to
+ indicate no overflow limit; no limit will be placed on the total number of concurrent
+ connections.
+
+ timeout=30 : the number of seconds to wait before giving up on returning a connection
+ """
def __init__(self, creator, pool_size = 5, max_overflow = 10, timeout=30, **params):
Pool.__init__(self, creator, **params)
self._pool = Queue.Queue(pool_size)
@@ -339,11 +383,55 @@ class QueuePool(Pool):
def checkedout(self):
return self._pool.maxsize - self._pool.qsize() + self._overflow
-
-class DBProxy(object):
+class NullPool(Pool):
+ """a Pool implementation which does not pool connections; instead
+ it literally opens and closes the underlying DBAPI connection per each connection open/close."""
+ def status(self):
+ return "NullPool"
+
+ def do_return_conn(self, conn):
+ conn.close()
+
+ def do_return_invalid(self, conn):
+ pass
+
+ def do_get(self):
+ return self.create_connection()
+
+class AssertionPool(Pool):
+ """a Pool implementation which will raise an exception
+ if more than one connection is checked out at a time. Useful for debugging
+ code that is using more connections than desired.
+
+ TODO: modify this to handle an arbitrary connection count."""
+ def __init__(self, creator, **params):
+ Pool.__init__(self, creator, **params)
+ self.connection = _ConnectionRecord(self)
+ self._conn = self.connection
+
+ def status(self):
+ return "AssertionPool"
+
+ def create_connection(self):
+ raise "Invalid"
+
+ def do_return_conn(self, conn):
+ assert conn is self._conn and self.connection is None
+ self.connection = conn
+
+ def do_return_invalid(self, conn):
+ raise "Invalid"
+
+ def do_get(self):
+ assert self.connection is not None
+ c = self.connection
+ self.connection = None
+ return c
+
+class _DBProxy(object):
"""proxies a DBAPI2 connect() call to a pooled connection keyed to the specific connect
- parameters."""
+ parameters. other attributes are proxied through via __getattr__."""
def __init__(self, module, poolclass = QueuePool, **params):
"""
@@ -362,7 +450,10 @@ class DBProxy(object):
def __del__(self):
self.close()
-
+
+ def __getattr__(self, key):
+ return getattr(self.module, key)
+
def get_pool(self, *args, **params):
key = self._serialize(*args, **params)
try: