util.failover: re-raise exceptions on failure

This commit is contained in:
Jimmy Zelinskie 2017-03-01 00:27:58 -05:00
parent 21b09a7451
commit cba7816caf
2 changed files with 19 additions and 13 deletions

View file

@ -7,11 +7,12 @@ logger = logging.getLogger(__name__)
class FailoverException(Exception): class FailoverException(Exception):
""" Exception raised when an operation should be retried by the failover decorator. """ """ Exception raised when an operation should be retried by the failover decorator.
def __init__(self, return_value, message): Wraps the exception of the initial failure.
"""
def __init__(self, exception):
super(FailoverException, self).__init__() super(FailoverException, self).__init__()
self.return_value = return_value self.exception = exception
self.message = message
def failover(func): def failover(func):
""" Wraps a function such that it can be retried on specified failures. """ Wraps a function such that it can be retried on specified failures.
@ -21,9 +22,10 @@ def failover(func):
@failover @failover
def get_google(scheme, use_www=False): def get_google(scheme, use_www=False):
www = 'www.' if use_www else '' www = 'www.' if use_www else ''
r = requests.get(scheme + '://' + www + 'google.com') try:
if r.status_code != 200: r = requests.get(scheme + '://' + www + 'google.com')
raise FailoverException('non 200 response from Google' ) except requests.RequestException as ex:
raise FailoverException(ex)
return r return r
def GooglePingTest(): def GooglePingTest():
@ -41,8 +43,8 @@ def failover(func):
try: try:
return func(*arg_set[0], **arg_set[1]) return func(*arg_set[0], **arg_set[1])
except FailoverException as ex: except FailoverException as ex:
logger.debug('failing over: %s', ex.message) logger.debug('failing over')
return_value = ex.return_value exception = ex.exception
continue continue
return return_value raise exception
return wrapper return wrapper

View file

@ -2,6 +2,9 @@ import pytest
from util.failover import failover, FailoverException from util.failover import failover, FailoverException
class FinishedException(Exception):
""" Exception raised at the end of every iteration to force failover. """
class Counter(object): class Counter(object):
""" Wraps a counter in an object so that it'll be passed by reference. """ """ Wraps a counter in an object so that it'll be passed by reference. """
@ -18,7 +21,7 @@ def my_failover_func(i, should_raise=None):
i.increment() i.increment()
if should_raise is not None: if should_raise is not None:
raise should_raise() raise should_raise()
raise FailoverException(None, 'incrementing') raise FailoverException(FinishedException())
@pytest.mark.parametrize('stop_on,exception', [ @pytest.mark.parametrize('stop_on,exception', [
@ -40,5 +43,6 @@ def test_readonly_failover(stop_on, exception):
with pytest.raises(exception): with pytest.raises(exception):
my_failover_func(*arg_sets) my_failover_func(*arg_sets)
else: else:
my_failover_func(*arg_sets) with pytest.raises(FinishedException):
assert counter.calls == stop_on my_failover_func(*arg_sets)
assert counter.calls == stop_on