2017-02-02 00:46:04 +00:00
|
|
|
import logging
|
|
|
|
|
|
|
|
from functools import wraps
|
|
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
class FailoverException(Exception):
|
2017-03-01 05:27:58 +00:00
|
|
|
""" Exception raised when an operation should be retried by the failover decorator.
|
|
|
|
Wraps the exception of the initial failure.
|
|
|
|
"""
|
|
|
|
def __init__(self, exception):
|
2017-02-02 00:46:04 +00:00
|
|
|
super(FailoverException, self).__init__()
|
2017-03-01 05:27:58 +00:00
|
|
|
self.exception = exception
|
2017-02-02 00:46:04 +00:00
|
|
|
|
|
|
|
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 ''
|
2017-03-01 05:27:58 +00:00
|
|
|
try:
|
|
|
|
r = requests.get(scheme + '://' + www + 'google.com')
|
|
|
|
except requests.RequestException as ex:
|
|
|
|
raise FailoverException(ex)
|
2017-02-02 00:46:04 +00:00
|
|
|
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:
|
2017-03-01 05:27:58 +00:00
|
|
|
logger.debug('failing over')
|
|
|
|
exception = ex.exception
|
2017-02-02 00:46:04 +00:00
|
|
|
continue
|
2017-03-01 05:27:58 +00:00
|
|
|
raise exception
|
2017-02-02 00:46:04 +00:00
|
|
|
return wrapper
|