b9bb788a2a
There appear to be timing issues for the diag requests. Somehow, we're sending out-of-date diagnostics and then not updating the UI when things change. That needs to be fixed.
81 lines
3.3 KiB
Python
81 lines
3.3 KiB
Python
#!/usr/bin/env python
|
|
#
|
|
# Copyright 2012 by Jeff Laughlin Consulting LLC
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
# of this software and associated documentation files (the "Software"), to deal
|
|
# in the Software without restriction, including without limitation the rights
|
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
# copies of the Software, and to permit persons to whom the Software is
|
|
# furnished to do so, subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be included in
|
|
# all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
# SOFTWARE.
|
|
|
|
|
|
import sys
|
|
from time import sleep
|
|
|
|
# Source: https://gist.github.com/n1ywb/2570004
|
|
|
|
def example_exc_handler(tries_remaining, exception, delay):
|
|
"""Example exception handler; prints a warning to stderr.
|
|
|
|
tries_remaining: The number of tries remaining.
|
|
exception: The exception instance which was raised.
|
|
"""
|
|
print >> sys.stderr, "Caught '%s', %d tries remaining, sleeping for %s seconds" % (exception, tries_remaining, delay)
|
|
|
|
|
|
def retries(max_tries, delay=1, backoff=2, exceptions=(Exception,), hook=None):
|
|
"""Function decorator implementing retrying logic.
|
|
|
|
delay: Sleep this many seconds * backoff * try number after failure
|
|
backoff: Multiply delay by this factor after each failure
|
|
exceptions: A tuple of exception classes; default (Exception,)
|
|
hook: A function with the signature myhook(tries_remaining, exception);
|
|
default None
|
|
|
|
The decorator will call the function up to max_tries times if it raises
|
|
an exception.
|
|
|
|
By default it catches instances of the Exception class and subclasses.
|
|
This will recover after all but the most fatal errors. You may specify a
|
|
custom tuple of exception classes with the 'exceptions' argument; the
|
|
function will only be retried if it raises one of the specified
|
|
exceptions.
|
|
|
|
Additionally you may specify a hook function which will be called prior
|
|
to retrying with the number of remaining tries and the exception instance;
|
|
see given example. This is primarily intended to give the opportunity to
|
|
log the failure. Hook is not called after failure if no retries remain.
|
|
"""
|
|
def dec(func):
|
|
def f2(*args, **kwargs):
|
|
mydelay = delay
|
|
tries = range(max_tries)
|
|
tries.reverse()
|
|
for tries_remaining in tries:
|
|
try:
|
|
return func(*args, **kwargs)
|
|
except exceptions as e:
|
|
if tries_remaining > 0:
|
|
if hook is not None:
|
|
hook(tries_remaining, e, mydelay)
|
|
sleep(mydelay)
|
|
mydelay = mydelay * backoff
|
|
else:
|
|
raise
|
|
else:
|
|
break
|
|
return f2
|
|
return dec
|