self.__connect(first_connect_check=True)
self.finalize_callback = deque()
+ fresh = False
+
fairy_ref = None
starttime = None
connection = pool._invoke_creator(self)
pool.logger.debug("Created new connection %r", connection)
self.connection = connection
+ self.fresh = True
except Exception as e:
pool.logger.debug("Error on connect(): %s", e)
raise
if fairy.connection is None:
raise exc.InvalidRequestError("This connection is closed")
fairy._counter += 1
-
if (
not pool.dispatch.checkout and not pool._pre_ping
) or fairy._counter != 1:
# here.
attempts = 2
while attempts > 0:
+ connection_is_fresh = fairy._connection_record.fresh
+ fairy._connection_record.fresh = False
try:
if pool._pre_ping:
- if fairy._echo:
- pool.logger.debug(
- "Pool pre-ping on connection %s", fairy.connection
- )
-
- result = pool._dialect.do_ping(fairy.connection)
- if not result:
+ if not connection_is_fresh:
if fairy._echo:
pool.logger.debug(
- "Pool pre-ping on connection %s failed, "
- "will invalidate pool",
+ "Pool pre-ping on connection %s",
fairy.connection,
)
- raise exc.InvalidatePoolError()
+ result = pool._dialect.do_ping(fairy.connection)
+ if not result:
+ if fairy._echo:
+ pool.logger.debug(
+ "Pool pre-ping on connection %s failed, "
+ "will invalidate pool",
+ fairy.connection,
+ )
+ raise exc.InvalidatePoolError()
+ elif fairy._echo:
+ pool.logger.debug(
+ "Connection %s is fresh, skipping pre-ping",
+ fairy.connection,
+ )
pool.dispatch.checkout(
fairy.connection, fairy._connection_record, fairy
from sqlalchemy.testing import eq_
from sqlalchemy.testing import expect_warnings
from sqlalchemy.testing import fixtures
+from sqlalchemy.testing import is_
from sqlalchemy.testing import is_false
from sqlalchemy.testing import is_true
from sqlalchemy.testing import mock
def setup(self):
self.dbapi = MockDBAPI()
- def _pool_fixture(self, pre_ping):
+ def _pool_fixture(self, pre_ping, pool_kw=None):
dialect = url.make_url(
"postgresql://foo:bar@localhost/test"
).get_dialect()()
creator=lambda: self.dbapi.connect("foo.db"),
pre_ping=pre_ping,
dialect=dialect,
+ **(pool_kw if pool_kw else {})
)
dialect.is_disconnect = lambda e, conn, cursor: isinstance(
def teardown(self):
self.dbapi.dispose()
+ def test_ping_not_on_first_connect(self):
+ pool = self._pool_fixture(
+ pre_ping=True, pool_kw=dict(pool_size=1, max_overflow=0)
+ )
+
+ conn = pool.connect()
+ dbapi_conn = conn.connection
+ eq_(dbapi_conn.mock_calls, [])
+ conn.close()
+
+ # no ping, so no cursor() call.
+ eq_(dbapi_conn.mock_calls, [call.rollback()])
+
+ conn = pool.connect()
+ is_(conn.connection, dbapi_conn)
+
+ # ping, so cursor() call.
+ eq_(dbapi_conn.mock_calls, [call.rollback(), call.cursor()])
+
+ conn.close()
+
+ conn = pool.connect()
+ is_(conn.connection, dbapi_conn)
+
+ # ping, so cursor() call.
+ eq_(
+ dbapi_conn.mock_calls,
+ [call.rollback(), call.cursor(), call.rollback(), call.cursor()],
+ )
+
+ conn.close()
+
+ def test_ping_not_on_reconnect(self):
+ pool = self._pool_fixture(
+ pre_ping=True, pool_kw=dict(pool_size=1, max_overflow=0)
+ )
+
+ conn = pool.connect()
+ dbapi_conn = conn.connection
+ conn_rec = conn._connection_record
+ eq_(dbapi_conn.mock_calls, [])
+ conn.close()
+
+ conn = pool.connect()
+ is_(conn.connection, dbapi_conn)
+ # ping, so cursor() call.
+ eq_(dbapi_conn.mock_calls, [call.rollback(), call.cursor()])
+
+ conn.invalidate()
+
+ is_(conn.connection, None)
+
+ # connect again, make sure we're on the same connection record
+ conn = pool.connect()
+ is_(conn._connection_record, conn_rec)
+
+ # no ping
+ dbapi_conn = conn.connection
+ eq_(dbapi_conn.mock_calls, [])
+
def test_connect_across_restart(self):
pool = self._pool_fixture(pre_ping=True)
old_dbapi_conn = conn.connection
conn.close()
- eq_(old_dbapi_conn.mock_calls, [call.cursor(), call.rollback()])
+ # no cursor() because no pre ping
+ eq_(old_dbapi_conn.mock_calls, [call.rollback()])
+
+ conn = pool.connect()
+ conn.close()
+
+ # connect again, we see pre-ping
+ eq_(
+ old_dbapi_conn.mock_calls,
+ [call.rollback(), call.cursor(), call.rollback()],
+ )
self.dbapi.shutdown("execute", stop=True)
self.dbapi.restart()
gc_collect()
# new connection was reset on return appropriately
- eq_(dbapi_conn.mock_calls, [call.cursor(), call.rollback()])
+ eq_(dbapi_conn.mock_calls, [call.rollback()])
# old connection was just closed - did not get an
# erroneous reset on return
eq_(
old_dbapi_conn.mock_calls,
- [call.cursor(), call.rollback(), call.cursor(), call.close()],
+ [
+ call.rollback(),
+ call.cursor(),
+ call.rollback(),
+ call.cursor(),
+ call.close(),
+ ],
)