mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-19 15:12:04 -04:00
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:
@@ -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
|
||||
|
||||
@@ -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",
|
||||
)
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user