Barry Warsaw pushed to branch master at mailman / Mailman

Commits:
856d239e by Mark Sapiro at 2017-03-27T11:36:55-07:00
Implement SQLAlchemy pre-ping to detect dropped connections.

- - - - -
21385905 by Barry Warsaw at 2017-03-27T21:06:46+00:00
Merge branch 'sa-ping' into 'master'

Implement SQLAlchemy pre-ping to detect dropped connections.

Closes #313

See merge request !254
- - - - -


2 changed files:

- src/mailman/database/base.py
- src/mailman/docs/NEWS.rst


Changes:

=====================================
src/mailman/database/base.py
=====================================
--- a/src/mailman/database/base.py
+++ b/src/mailman/database/base.py
@@ -23,7 +23,7 @@ from mailman.config import config
 from mailman.interfaces.database import IDatabase
 from mailman.utilities.string import expand
 from public import public
-from sqlalchemy import create_engine
+from sqlalchemy import create_engine, event, exc, select
 from sqlalchemy.orm import sessionmaker
 from zope.interface import implementer
 
@@ -107,3 +107,43 @@ class SABaseDatabase:
         session = sessionmaker(bind=self.engine)
         self.store = session()
         self.store.commit()
+        # This is from the Dealing with Disconnects section at
+        # <http://docs.sqlalchemy.org/en/latest/core/pooling.html>.  It
+        # establishes connection pinging to deal with lost connections due to
+        # database server restarts or other outside events.
+        #
+        # XXX This can all be removed once SQLAlchemy 1.2 is released, and we
+        # pass `pool_pre_ping=True` to create_engine().
+        @event.listens_for(self.engine, 'engine_connect')   # noqa: E306
+        def ping_connection(connection, branch):            # pragma: no cover
+            if branch:
+                # "branch" refers to a sub-connection of a connection;
+                # we don't want to bother pinging on these.
+                return
+            # Turn off "close with result".  This flag is only used with
+            # "connectionless" execution, otherwise will be False in any case.
+            old_scwr = connection.should_close_with_result
+            connection.should_close_with_result = False
+            try:
+                # Run a SELECT 1.  Use a core select() so that the SELECT of a
+                # scalar value without a table is appropriately formatted for
+                # the backend.
+                connection.scalar(select([1]))
+            except exc.DBAPIError as error:
+                # Catch SQLAlchemy's DBAPIError, which is a wrapper for the
+                # DBAPI's exception.  It includes a .connection_invalidated
+                # attribute which specifies if this connection is a
+                # "disconnect" condition, which is based on inspection of the
+                # original exception by the dialect in use.
+                if error.connection_invalidated:
+                    # Run the same SELECT again - the connection will
+                    # re-validate itself and establish a new connection.  The
+                    # disconnect detection here also causes the whole
+                    # connection pool to be invalidated so that all stale
+                    # connections are discarded.
+                    connection.scalar(select([1]))
+                else:
+                    raise
+            finally:
+                # Restore "close with result".
+                connection.should_close_with_result = old_scwr


=====================================
src/mailman/docs/NEWS.rst
=====================================
--- a/src/mailman/docs/NEWS.rst
+++ b/src/mailman/docs/NEWS.rst
@@ -140,6 +140,9 @@ Command line
 Database
 --------
  * MySQL is now an officially supported database.  Given by Abhilash Raj.
+ * Fix a problem with tracebacks when a PostgreSQL database is power cycled
+   while Mailman is still running.  This ports an upstream SQLAlchemy fix to
+   Mailman in lieu of a future SQLAlchemy 1.2 release.  (Closes: #313)
 
 Interfaces
 ----------



View it on GitLab: 
https://gitlab.com/mailman/mailman/compare/775216d81ba75e00bfcbb482e075f473d12e99c4...213859054668ad64c0ea66f188beb1c239e4a0c0
_______________________________________________
Mailman-checkins mailing list
Mailman-checkins@python.org
Unsubscribe: 
https://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org

Reply via email to