From: Daniele Varrazzo Date: Sun, 21 Feb 2021 03:47:20 +0000 (+0100) Subject: Add separate setup_timeout param for pool X-Git-Tag: 3.0.dev0~87^2~57 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=87b8eebcbdb8bd1df0d5ee8b6699971bbac53a7c;p=thirdparty%2Fpsycopg.git Add separate setup_timeout param for pool Allow 0 too, which would fill the pool in background. --- diff --git a/psycopg3/psycopg3/pool.py b/psycopg3/psycopg3/pool.py index 33d2bd85b..8c62faaa3 100644 --- a/psycopg3/psycopg3/pool.py +++ b/psycopg3/psycopg3/pool.py @@ -46,6 +46,7 @@ class ConnectionPool: maxconn: Optional[int] = None, name: Optional[str] = None, timeout: float = 30.0, + setup_timeout: float = 30.0, max_idle: float = 10 * 60.0, reconnect_timeout: float = 5 * 60.0, reconnect_failed: Optional[Callable[["ConnectionPool"], None]] = None, @@ -100,16 +101,21 @@ class ConnectionPool: self._sched_runner.start() # Populate the pool with initial minconn connections - event = threading.Event() - for i in range(self._nconns): - self.add_task(AddInitialConnection(self, event)) - - # Wait for the pool to be full or throw an error - if not event.wait(timeout=timeout): - self.close() # stop all the threads - raise PoolTimeout( - f"pool initialization incomplete after {timeout} sec" - ) + # Block if setup_timeout is > 0, otherwise fill the pool in background + if setup_timeout > 0: + event = threading.Event() + for i in range(self._nconns): + self.add_task(AddInitialConnection(self, event)) + + # Wait for the pool to be full or throw an error + if not event.wait(timeout=setup_timeout): + self.close() # stop all the threads + raise PoolTimeout( + f"pool initialization incomplete after {setup_timeout} sec" + ) + else: + for i in range(self._nconns): + self.add_task(AddConnection(self)) def __repr__(self) -> str: return ( diff --git a/tests/test_pool.py b/tests/test_pool.py index a623d8162..14e68c0ec 100644 --- a/tests/test_pool.py +++ b/tests/test_pool.py @@ -73,17 +73,35 @@ def test_concurrent_filling(dsn, monkeypatch): @pytest.mark.slow -def test_init_timeout(dsn, monkeypatch): +def test_setup_timeout(dsn, monkeypatch): delay_connection(monkeypatch, 0.1) with pytest.raises(pool.PoolTimeout): - pool.ConnectionPool(dsn, minconn=4, num_workers=1, timeout=0.3) + pool.ConnectionPool(dsn, minconn=4, num_workers=1, setup_timeout=0.3) - p = pool.ConnectionPool(dsn, minconn=4, num_workers=1, timeout=0.5) + p = pool.ConnectionPool(dsn, minconn=4, num_workers=1, setup_timeout=0.5) p.close() - p = pool.ConnectionPool(dsn, minconn=4, num_workers=2, timeout=0.3) + p = pool.ConnectionPool(dsn, minconn=4, num_workers=2, setup_timeout=0.3) p.close() +@pytest.mark.slow +def test_setup_no_timeout(dsn, proxy): + with pytest.raises(pool.PoolTimeout): + pool.ConnectionPool( + proxy.client_dsn, minconn=1, num_workers=1, setup_timeout=0.2 + ) + + p = pool.ConnectionPool( + proxy.client_dsn, minconn=1, num_workers=1, setup_timeout=0 + ) + sleep(0.5) + assert not p._pool + proxy.start() + + with p.connection() as conn: + conn.execute("select 1") + + @pytest.mark.slow def test_queue(dsn): p = pool.ConnectionPool(dsn, minconn=2) @@ -446,7 +464,7 @@ def test_reconnect(proxy, caplog, monkeypatch): monkeypatch.setattr(pool.AddConnection, "DELAY_JITTER", 0.0) proxy.start() - p = pool.ConnectionPool(proxy.client_dsn, minconn=1, timeout=2) + p = pool.ConnectionPool(proxy.client_dsn, minconn=1, setup_timeout=2.0) proxy.stop() with pytest.raises(psycopg3.OperationalError): @@ -486,7 +504,7 @@ def test_reconnect_failure(proxy): proxy.client_dsn, name="this-one", minconn=1, - timeout=2, + setup_timeout=2.0, reconnect_timeout=1.0, reconnect_failed=failed, )