diff --git a/setup.py b/setup.py index 98cb4b9f..da99d2e4 100644 --- a/setup.py +++ b/setup.py @@ -64,13 +64,6 @@ requires = [ # # package # low high - # TODO: Pyramid 1.9 looks like it breaks us..? playing it safe for now.. - 'pyramid<1.9', # 1.3b2 1.8.3 - - # apparently 2.0 removes the retry support, in which case we then need - # pyramid_retry .. but that requires pyramid 1.9 ... - 'pyramid_tm<2.0', # 0.3 1.1.1 - # TODO: why do we need to cap this? breaks tailbone.db zope stuff somehow 'zope.sqlalchemy<1.0', # 0.7 0.7.7 @@ -82,10 +75,12 @@ requires = [ 'paginate', # 0.5.6 'paginate_sqlalchemy', # 0.2.0 'passlib', # 1.7.1 + 'pyramid', # 1.3b2 'pyramid_beaker>=0.6', # 0.6.1 'pyramid_deform', # 0.2 'pyramid_exclog', # 0.6 'pyramid_mako', # 1.0.2 + 'pyramid_tm', # 0.3 'rattail[db,bouncer]', # 0.5.0 'six', # 1.10.0 'transaction', # 1.2.0 diff --git a/tailbone/tweens.py b/tailbone/tweens.py index 6df4be16..f944a66f 100644 --- a/tailbone/tweens.py +++ b/tailbone/tweens.py @@ -29,32 +29,46 @@ from __future__ import unicode_literals, absolute_import import six from sqlalchemy.exc import OperationalError -from transaction.interfaces import TransientError - def sqlerror_tween_factory(handler, registry): """ Produces a tween which will convert ``sqlalchemy.exc.OperationalError`` - instances (caused by database server restart) into a retryable - ``transaction.interfaces.TransientError`` instance, so that a second - attempt may be made to connect to the database before really giving up. + instances (caused by database server restart) into a retryable error + instance, so that a second attempt may be made to connect to the database + before really giving up. .. note:: This tween alone is not enough to cause the transaction to be retried; it only marks the error as being *retryable*. If you wish more than one - attempt to be made, you must define the ``tm.attempts`` setting within - your Pyramid app configuration. For more info see `Retrying`_. + attempt to be made, you must define the ``retry.attempts`` (or + ``tm.attempts`` if running pyramid<1.9) setting within your Pyramid app + configuration. For more info see `Retrying`_. .. _Retrying: http://docs.pylonsproject.org/projects/pyramid_tm/en/latest/#retrying """ def sqlerror_tween(request): + try: + from pyramid_retry import mark_error_retryable + except ImportError: + mark_error_retryable = None + from transaction.interfaces import TransientError + try: response = handler(request) except OperationalError as error: + + # if connection is invalid, allow retry if error.connection_invalidated: - raise TransientError(six.text_type(error)) + if mark_error_retryable: + mark_error_retryable(error) + raise error + else: + raise TransientError(six.text_type(error)) + + # if connection was *not* invalid, raise original error raise + return response return sqlerror_tween