[Sqlalchemy-tickets] Issue #3419: connection record not immediately checked back in when connection
Brought to you by:
zzzeek
|
From: Mike B. <iss...@bi...> - 2015-05-14 17:50:27
|
New issue 3419: connection record not immediately checked back in when connection fails after failed checkout event handler https://bitbucket.org/zzzeek/sqlalchemy/issue/3419/connection-record-not-immediately-checked Mike Bayer: ``` #!python from sqlalchemy import event import mock import sys import sqlalchemy as sa engine = sa.create_engine( "postgresql://scott:tiger@localhost/test", pool_size=1, max_overflow=0, pool_timeout=0, pool_recycle=3600) @event.listens_for(engine, 'checkout') def handle_checkout_event(dbapi_con, con_record, con_proxy): try: with dbapi_con.cursor() as cur: cur.execute("SELECT 1") cur.fetchone() except Exception: raise sa.exc.DisconnectionError() # act as though the DB is turned off conn = engine.connect() dbapi_conn = conn.connection.connection conn.close() dbapi_conn.close() def shutdown_backend(): raise dbapi_conn.OperationalError("closed the connection") patcher = mock.patch.object(engine.pool, "_creator", shutdown_backend) patcher.start() try: with engine.begin() as conn: pass except sa.exc.OperationalError as e: print >>sys.stderr, "Got an (expected) error: ", e # sys.exc_clear() try: with engine.begin() as conn: pass except sa.exc.OperationalError as e: print >>sys.stderr, "Got an (expected) error: ", e assert True ``` the pool checkout fails on the second run because the single ConnectionRecord hasn't been checked in. ``` #!diff diff --git a/lib/sqlalchemy/pool.py b/lib/sqlalchemy/pool.py index 0a4cdad..b38aefb 100644 --- a/lib/sqlalchemy/pool.py +++ b/lib/sqlalchemy/pool.py @@ -732,7 +732,13 @@ class _ConnectionFairy(object): pool.logger.info( "Disconnection detected on checkout: %s", e) fairy._connection_record.invalidate(e) - fairy.connection = fairy._connection_record.get_connection() + try: + fairy.connection = \ + fairy._connection_record.get_connection() + except: + with util.safe_reraise(): + fairy._connection_record.checkin() + attempts -= 1 pool.logger.info("Reconnection attempts exhausted on checkout") ``` |