Refactor sqlerror tween to add support for pyramid_retry
hopefully this doesn't break anything else..
This commit is contained in:
		
							parent
							
								
									56392ccdd0
								
							
						
					
					
						commit
						528c0f9622
					
				
					 2 changed files with 24 additions and 15 deletions
				
			
		
							
								
								
									
										9
									
								
								setup.py
									
										
									
									
									
								
							
							
						
						
									
										9
									
								
								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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue