summaryrefslogtreecommitdiff
path: root/oslo
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2014-07-25 10:28:59 +0000
committerGerrit Code Review <review@openstack.org>2014-07-25 10:28:59 +0000
commitbb03d7e1ce18f523d6f0766a27dc97a173fedb45 (patch)
tree9f774e571c226ae57c3be727777a58e5d9414ad2 /oslo
parentbbfe7e056f6b5c22e9c7e61f3a3935a0710535db (diff)
parent9d5ab2af1163ec2ad46686c60422ecb3b18c6eb1 (diff)
downloadoslo-db-bb03d7e1ce18f523d6f0766a27dc97a173fedb45.tar.gz
Merge "Integrate the ping listener into the filter system."
Diffstat (limited to 'oslo')
-rw-r--r--oslo/db/sqlalchemy/session.py54
1 files changed, 23 insertions, 31 deletions
diff --git a/oslo/db/sqlalchemy/session.py b/oslo/db/sqlalchemy/session.py
index 13eb118..2b5a0e7 100644
--- a/oslo/db/sqlalchemy/session.py
+++ b/oslo/db/sqlalchemy/session.py
@@ -289,7 +289,9 @@ from sqlalchemy.interfaces import PoolListener
import sqlalchemy.orm
from sqlalchemy.pool import NullPool, StaticPool
from sqlalchemy.sql.expression import literal_column
+from sqlalchemy.sql.expression import select
+from oslo.db import exception
from oslo.db.openstack.common.gettextutils import _LW
from oslo.db.openstack.common import timeutils
from oslo.db import options
@@ -335,34 +337,23 @@ def _thread_yield(dbapi_con, con_record):
time.sleep(0)
-def _ping_listener(engine, dbapi_conn, connection_rec, connection_proxy):
- """Ensures that MySQL, PostgreSQL or DB2 connections are alive.
+def _begin_ping_listener(connection):
+ """Ping the server at transaction begin and transparently reconnect
+ if a disconnect exception occurs.
- Borrowed from:
- http://groups.google.com/group/sqlalchemy/msg/a4ce563d802c929f
"""
- cursor = dbapi_conn.cursor()
try:
- ping_sql = 'select 1'
- if engine.name == 'ibm_db_sa':
- # DB2 requires a table expression
- ping_sql = 'select 1 from (values (1)) AS t1'
- cursor.execute(ping_sql)
- except Exception as ex:
- if engine.dialect.is_disconnect(ex, dbapi_conn, cursor):
- msg = _LW('Database server has gone away: %s') % ex
- LOG.warning(msg)
-
- # if the database server has gone away, all connections in the pool
- # have become invalid and we can safely close all of them here,
- # rather than waste time on checking of every single connection
- engine.dispose()
-
- # this will be handled by SQLAlchemy and will force it to create
- # a new connection and retry the original action
- raise sqla_exc.DisconnectionError(msg)
- else:
- raise
+ # run a SELECT 1. use a core select() so that
+ # any details like that needed by Oracle, DB2 etc. are handled.
+ connection.scalar(select([1]))
+ except exception.DBConnectionError:
+ # catch DBConnectionError, which is raised by the filter
+ # system.
+ # disconnect detected. The connection is now
+ # "invalid", but the pool should be ready to return
+ # new connections assuming they are good now.
+ # run the select again to re-validate the Connection.
+ connection.scalar(select([1]))
def _set_session_sql_mode(dbapi_con, connection_rec, sql_mode=None):
@@ -482,12 +473,9 @@ def create_engine(sql_connection, sqlite_fk=False, mysql_sql_mode=None,
if thread_checkin:
sqlalchemy.event.listen(engine, 'checkin', _thread_yield)
- if engine.name in ('ibm_db_sa', 'mysql', 'postgresql'):
- ping_callback = functools.partial(_ping_listener, engine)
- sqlalchemy.event.listen(engine, 'checkout', ping_callback)
- if engine.name == 'mysql':
- if mysql_sql_mode is not None:
- _mysql_set_mode_callback(engine, mysql_sql_mode)
+ if engine.name == 'mysql':
+ if mysql_sql_mode is not None:
+ _mysql_set_mode_callback(engine, mysql_sql_mode)
elif 'sqlite' in connection_dict.drivername:
if not sqlite_synchronous:
sqlalchemy.event.listen(engine, 'connect',
@@ -522,6 +510,10 @@ def create_engine(sql_connection, sqlite_fk=False, mysql_sql_mode=None,
# register alternate exception handler
exc_filters.register_engine(engine)
+
+ # register on begin handler
+ sqlalchemy.event.listen(engine, "begin", _begin_ping_listener)
+
return engine