Fixes: #5719
<!-- Provide a general summary of your proposed changes in the Title field above -->
### Description
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.
### Checklist
<!-- go over following points. check them with an `x` if they do apply, (they turn into clickable checkboxes once the PR is submitted, so no need to do everything at once)
-->
This pull request is:
- [ ] A documentation / typographical error fix
- Good to go, no issue or tests are needed
- [x] A short code fix
- please include the issue number, and create an issue if none exists, which
must include a complete example of the issue. one line code fixes without an
issue and demonstration will not be accepted.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests. one line code fixes without tests will not be accepted.
- [ ] A new feature implementation
- please include the issue number, and create an issue if none exists, which must
include a complete example of how the feature would look.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.
**Have a nice day!**
Closes: #5710
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/5710
Pull-request-sha:
5f4eef8b4aba756d32e14ea41f71ef2919c26b84
Change-Id: I462524b1624ca5cc76d083a1d58e5dc89501c1a9
--- /dev/null
+.. change::
+ :tags: pool, tests, usecase
+ :tickets: 5582
+
+ Improve documentation and add test for sub-second pool timeouts.
+ Pull request courtesy Jordan Pittier.
: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
creator,
pool_size=5,
max_overflow=10,
- timeout=30,
+ timeout=30.0,
use_lifo=False,
**kw
):
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
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",
)
from sqlalchemy.testing import assert_raises_context_ok
from sqlalchemy.testing import assert_raises_message
from sqlalchemy.testing import eq_
+from sqlalchemy.testing import expect_raises
from sqlalchemy.testing import fixtures
from sqlalchemy.testing import is_
from sqlalchemy.testing import is_not
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 expect_raises(tsa.exc.TimeoutError):
+ 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):