From: Daniele Varrazzo Date: Tue, 6 Sep 2022 16:53:40 +0000 (+0100) Subject: fix(pool): allow growing again after failing a growing connection attempt X-Git-Tag: pool-3.1.2~1^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b18b748ee362e5881477aa9028312df270497c99;p=thirdparty%2Fpsycopg.git fix(pool): allow growing again after failing a growing connection attempt Fix #370 --- diff --git a/docs/news_pool.rst b/docs/news_pool.rst index f4aef6abe..b2ecf0bbc 100644 --- a/docs/news_pool.rst +++ b/docs/news_pool.rst @@ -7,6 +7,16 @@ ``psycopg_pool`` release notes ============================== +Future releases +--------------- + +psycopg_pool 3.1.2 (unreleased) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Fix possible failure to reconnect after losing connection from the server + (:ticket:`#370`). + + Current release --------------- diff --git a/psycopg_pool/psycopg_pool/pool.py b/psycopg_pool/psycopg_pool/pool.py index 9eb052e4c..0f3cf535a 100644 --- a/psycopg_pool/psycopg_pool/pool.py +++ b/psycopg_pool/psycopg_pool/pool.py @@ -527,6 +527,9 @@ class ConnectionPool(BasePool[Connection[Any]]): ) with self._lock: self._nconns -= 1 + # If we have given up with a growing attempt, allow a new one. + if growing and self._growing: + self._growing = False self.reconnect_failed() else: attempt.update_delay(now) diff --git a/psycopg_pool/psycopg_pool/pool_async.py b/psycopg_pool/psycopg_pool/pool_async.py index 864a50019..e54d7b19a 100644 --- a/psycopg_pool/psycopg_pool/pool_async.py +++ b/psycopg_pool/psycopg_pool/pool_async.py @@ -428,6 +428,9 @@ class AsyncConnectionPool(BasePool[AsyncConnection[Any]]): ) async with self._lock: self._nconns -= 1 + # If we have given up with a growing attempt, allow a new one. + if growing and self._growing: + self._growing = False self.reconnect_failed() else: attempt.update_delay(now) diff --git a/tests/pool/test_pool.py b/tests/pool/test_pool.py index 008905411..51d800a82 100644 --- a/tests/pool/test_pool.py +++ b/tests/pool/test_pool.py @@ -921,6 +921,33 @@ def test_reconnect_failure(proxy): assert t1 - t0 < 0.2 +@pytest.mark.slow +def test_reconnect_retry(proxy): + proxy.stop() + + ev = Event() + + def failed(pool): + ev.set() + + with pool.ConnectionPool( + proxy.client_dsn, reconnect_timeout=1.0, reconnect_failed=failed + ) as p: + assert ev.wait(timeout=2) + + with pytest.raises(pool.PoolTimeout): + with p.connection(timeout=0.5) as conn: + pass + + ev.clear() + assert ev.wait(timeout=2) + + proxy.start() + + with p.connection(timeout=2) as conn: + conn.execute("select 1") + + @pytest.mark.slow def test_uniform_use(dsn): with pool.ConnectionPool(dsn, min_size=4) as p: diff --git a/tests/pool/test_pool_async.py b/tests/pool/test_pool_async.py index b67a575e1..6c923e638 100644 --- a/tests/pool/test_pool_async.py +++ b/tests/pool/test_pool_async.py @@ -873,6 +873,33 @@ async def test_reconnect_failure(proxy): assert t1 - t0 < 0.2 +@pytest.mark.slow +async def test_reconnect_retry(proxy): + proxy.stop() + + ev = asyncio.Event() + + def failed(pool): + ev.set() + + async with pool.AsyncConnectionPool( + proxy.client_dsn, reconnect_timeout=1.0, reconnect_failed=failed + ) as p: + await asyncio.wait_for(ev.wait(), 2.0) + + with pytest.raises(pool.PoolTimeout): + async with p.connection(timeout=0.5) as conn: + pass + + ev.clear() + await asyncio.wait_for(ev.wait(), 2.0) + + proxy.start() + + async with p.connection(timeout=2) as conn: + await conn.execute("select 1") + + @pytest.mark.slow async def test_uniform_use(dsn): async with pool.AsyncConnectionPool(dsn, min_size=4) as p: