2017-02-02 00:46:04 +00:00
|
|
|
import logging
|
|
|
|
|
|
|
|
from functools import wraps
|
|
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
class FailoverException(Exception):
|
|
|
|
""" Exception raised when an operation should be retried by the failover decorator. """
|
2017-02-14 19:33:11 +00:00
|
|
|
def __init__(self, return_value, message):
|
2017-02-02 00:46:04 +00:00
|
|
|
super(FailoverException, self).__init__()
|
2017-02-14 19:33:11 +00:00
|
|
|
self.return_value = return_value
|
2017-02-02 00:46:04 +00:00
|
|
|
self.message = message
|
|
|
|
|
|
|
|
def failover(func):
|
|
|
|
""" Wraps a function such that it can be retried on specified failures.
|
|
|
|
Raises FailoverException when all failovers are exhausted.
|
|
|
|
Example:
|
|
|
|
|
|
|
|
@failover
|
|
|
|
def get_google(scheme, use_www=False):
|
|
|
|
www = 'www.' if use_www else ''
|
|
|
|
r = requests.get(scheme + '://' + www + 'google.com')
|
|
|
|
if r.status_code != 200:
|
|
|
|
raise FailoverException('non 200 response from Google' )
|
|
|
|
return r
|
|
|
|
|
|
|
|
def GooglePingTest():
|
|
|
|
r = get_google(
|
|
|
|
(('http'), {'use_www': False}),
|
|
|
|
(('http'), {'use_www': True}),
|
|
|
|
(('https'), {'use_www': False}),
|
|
|
|
(('https'), {'use_www': True}),
|
|
|
|
)
|
|
|
|
print('Successfully contacted ' + r.url)
|
|
|
|
"""
|
|
|
|
@wraps(func)
|
|
|
|
def wrapper(*args_sets):
|
|
|
|
for arg_set in args_sets:
|
|
|
|
try:
|
|
|
|
return func(*arg_set[0], **arg_set[1])
|
|
|
|
except FailoverException as ex:
|
|
|
|
logger.debug('failing over: %s', ex.message)
|
2017-02-14 19:33:11 +00:00
|
|
|
return_value = ex.return_value
|
2017-02-02 00:46:04 +00:00
|
|
|
continue
|
2017-02-14 19:33:11 +00:00
|
|
|
return return_value
|
2017-02-02 00:46:04 +00:00
|
|
|
return wrapper
|