QueuePool: support subsecond timeout

Make it explicit in the documentation and in the default value for the 'timeout'
parameter that `timeout` can be a float. Because Python timing is not
very accurate, warn about the precision.
This commit is contained in:
Jordan Pittier
2020-11-18 11:23:12 +01:00
parent ea3f4fa9ff
commit 5f4eef8b4a
3 changed files with 22 additions and 5 deletions
+4 -2
View File
@@ -440,9 +440,11 @@ def create_engine(url, **kwargs):
:paramref:`_pool.Pool.reset_on_return`
:param pool_timeout=30: number of seconds to wait before giving
:param pool_timeout=30.0: number of seconds to wait before giving
up on getting a connection from the pool. This is only used
with :class:`~sqlalchemy.pool.QueuePool`.
with :class:`~sqlalchemy.pool.QueuePool`. This can be a float but is
subject to the limitations of Python time functions which may not be
reliable in the tens of milliseconds.
:param pool_use_lifo=False: use LIFO (last-in-first-out) when retrieving
connections from :class:`.QueuePool` instead of FIFO
+5 -3
View File
@@ -40,7 +40,7 @@ class QueuePool(Pool):
creator,
pool_size=5,
max_overflow=10,
timeout=30,
timeout=30.0,
use_lifo=False,
**kw
):
@@ -73,7 +73,9 @@ class QueuePool(Pool):
connections. Defaults to 10.
:param timeout: The number of seconds to wait before giving up
on returning a connection. Defaults to 30.
on returning a connection. Defaults to 30.0. This can be a float
but is subject to the limitations of Python time functions which
may not be reliable in the tens of milliseconds.
:param use_lifo: use LIFO (last-in-first-out) when retrieving
connections instead of FIFO (first-in-first-out). Using LIFO, a
@@ -129,7 +131,7 @@ class QueuePool(Pool):
else:
raise exc.TimeoutError(
"QueuePool limit of size %d overflow %d reached, "
"connection timed out, timeout %d"
"connection timed out, timeout %0.2f"
% (self.size(), self.overflow(), self._timeout),
code="3o7r",
)
+13
View File
@@ -4,6 +4,8 @@ import threading
import time
import weakref
import pytest
import sqlalchemy as tsa
from sqlalchemy import event
from sqlalchemy import pool
@@ -866,6 +868,17 @@ class QueuePoolTest(PoolTestBase):
assert_raises(tsa.exc.TimeoutError, p.connect)
assert int(time.time() - now) == 2
@testing.requires.timing_intensive
def test_timeout_subsecond_precision(self):
p = self._queuepool_fixture(pool_size=1, max_overflow=0, timeout=0.5)
c1 = p.connect() # noqa
with pytest.raises(tsa.exc.TimeoutError, match=r".* timeout 0.50 .*"):
now = time.time()
c2 = p.connect() # noqa
# Python timing is not very accurate, the time diff should be very
# close to 0.5s but we give 200ms of slack.
assert 0.3 <= time.time() - now <= 0.7, "Pool timeout not respected"
@testing.requires.threading_with_mock
@testing.requires.timing_intensive
def test_timeout_race(self):