- changed status to resolved
connection record not immediately checked back in when connection fails after failed checkout event handler
Issue #3419
resolved
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 --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")
Comments (1)
-
reporter - Log in to comment
#3419→ <<cset 4a0e51e7d2f3>>