summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authormike bayer <mike_mp@zzzcomputing.com>2018-09-18 23:29:34 -0400
committerGerrit Code Review <gerrit@ci.zzzcomputing.com>2018-09-18 23:29:34 -0400
commit5981e4328193bd760c4e2b28fdb8451f0f55c4ea (patch)
treee2704e20fa414f3e8ababdfad9b9f919021881e9 /lib/sqlalchemy
parent505941259e4e7181a176e74b3de0b7d96c444e29 (diff)
parentb64a3dd87a4204ce6d4f2793a7a3f7fbf72eb01f (diff)
downloadsqlalchemy-5981e4328193bd760c4e2b28fdb8451f0f55c4ea.tar.gz
Merge "Add LIFO for connection pooling"
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/engine/__init__.py15
-rw-r--r--lib/sqlalchemy/engine/strategies.py3
-rw-r--r--lib/sqlalchemy/pool/impl.py19
-rw-r--r--lib/sqlalchemy/util/queue.py13
4 files changed, 45 insertions, 5 deletions
diff --git a/lib/sqlalchemy/engine/__init__.py b/lib/sqlalchemy/engine/__init__.py
index b0d765b8e..d7197fe74 100644
--- a/lib/sqlalchemy/engine/__init__.py
+++ b/lib/sqlalchemy/engine/__init__.py
@@ -399,6 +399,21 @@ def create_engine(*args, **kwargs):
up on getting a connection from the pool. This is only used
with :class:`~sqlalchemy.pool.QueuePool`.
+ :param pool_use_lifo=False: use LIFO (last-in-first-out) when retrieving
+ connections from :class:`.QueuePool` instead of FIFO
+ (first-in-first-out). Using LIFO, a server-side timeout scheme can
+ reduce the number of connections used during non- peak periods of
+ use. When planning for server-side timeouts, ensure that a recycle or
+ pre-ping strategy is in use to gracefully handle stale connections.
+
+ .. versionadded:: 1.3
+
+ .. seealso::
+
+ :ref:`pool_use_lifo`
+
+ :ref:`pool_disconnects`
+
:param plugins: string list of plugin names to load. See
:class:`.CreateEnginePlugin` for background.
diff --git a/lib/sqlalchemy/engine/strategies.py b/lib/sqlalchemy/engine/strategies.py
index 0ec6aa06f..d4f5185de 100644
--- a/lib/sqlalchemy/engine/strategies.py
+++ b/lib/sqlalchemy/engine/strategies.py
@@ -123,7 +123,8 @@ class DefaultEngineStrategy(EngineStrategy):
'events': 'pool_events',
'use_threadlocal': 'pool_threadlocal',
'reset_on_return': 'pool_reset_on_return',
- 'pre_ping': 'pool_pre_ping'}
+ 'pre_ping': 'pool_pre_ping',
+ 'use_lifo': 'pool_use_lifo'}
for k in util.get_cls_kwargs(poolclass):
tk = translate.get(k, k)
if tk in kwargs:
diff --git a/lib/sqlalchemy/pool/impl.py b/lib/sqlalchemy/pool/impl.py
index c45661895..3058d6247 100644
--- a/lib/sqlalchemy/pool/impl.py
+++ b/lib/sqlalchemy/pool/impl.py
@@ -30,7 +30,7 @@ class QueuePool(Pool):
"""
- def __init__(self, creator, pool_size=5, max_overflow=10, timeout=30,
+ def __init__(self, creator, pool_size=5, max_overflow=10, timeout=30, use_lifo=False,
**kw):
r"""
Construct a QueuePool.
@@ -63,6 +63,21 @@ class QueuePool(Pool):
:param timeout: The number of seconds to wait before giving up
on returning a connection. Defaults to 30.
+ :param use_lifo: use LIFO (last-in-first-out) when retrieving
+ connections instead of FIFO (first-in-first-out). Using LIFO, a
+ server-side timeout scheme can reduce the number of connections used
+ during non-peak periods of use. When planning for server-side
+ timeouts, ensure that a recycle or pre-ping strategy is in use to
+ gracefully handle stale connections.
+
+ .. versionadded:: 1.3
+
+ .. seealso::
+
+ :ref:`pool_use_lifo`
+
+ :ref:`pool_disconnects`
+
:param \**kw: Other keyword arguments including
:paramref:`.Pool.recycle`, :paramref:`.Pool.echo`,
:paramref:`.Pool.reset_on_return` and others are passed to the
@@ -70,7 +85,7 @@ class QueuePool(Pool):
"""
Pool.__init__(self, creator, **kw)
- self._pool = sqla_queue.Queue(pool_size)
+ self._pool = sqla_queue.Queue(pool_size, use_lifo=use_lifo)
self._overflow = 0 - pool_size
self._max_overflow = max_overflow
self._timeout = timeout
diff --git a/lib/sqlalchemy/util/queue.py b/lib/sqlalchemy/util/queue.py
index 1958702c7..640f70ea9 100644
--- a/lib/sqlalchemy/util/queue.py
+++ b/lib/sqlalchemy/util/queue.py
@@ -39,10 +39,12 @@ class Full(Exception):
class Queue:
- def __init__(self, maxsize=0):
+ def __init__(self, maxsize=0, use_lifo=False):
"""Initialize a queue object with a given maximum size.
If `maxsize` is <= 0, the queue size is infinite.
+
+ If `use_lifo` is True, this Queue acts like a Stack (LIFO).
"""
self._init(maxsize)
@@ -57,6 +59,8 @@ class Queue:
# Notify not_full whenever an item is removed from the queue;
# a thread waiting to put is notified then.
self.not_full = threading.Condition(self.mutex)
+ # If this queue uses LIFO or FIFO
+ self.use_lifo = use_lifo
def qsize(self):
"""Return the approximate size of the queue (not reliable!)."""
@@ -196,4 +200,9 @@ class Queue:
# Get an item from the queue
def _get(self):
- return self.queue.popleft()
+ if self.use_lifo:
+ # LIFO
+ return self.queue.pop()
+ else:
+ # FIFO
+ return self.queue.popleft()