diff --git a/bots/zephyr_mirror.py b/bots/zephyr_mirror.py index a976131..a3375ca 100755 --- a/bots/zephyr_mirror.py +++ b/bots/zephyr_mirror.py @@ -28,7 +28,6 @@ import traceback import signal from zephyr_mirror_backend import parse_args -from zephyr_mirror_backend import RandomExponentialBackoff def die(signal, frame): # We actually want to exit, so run os._exit (so as not to be caught and restarted) @@ -38,6 +37,9 @@ signal.signal(signal.SIGINT, die) (options, args) = parse_args() +sys.path[:0] = [os.path.join(options.root_path, 'api')] +from zulip import RandomExponentialBackoff + args = [os.path.join(options.root_path, "user_root", "zephyr_mirror_backend.py")] args.extend(sys.argv[1:]) diff --git a/bots/zephyr_mirror_backend.py b/bots/zephyr_mirror_backend.py index 9b92b3a..9d9a4bd 100755 --- a/bots/zephyr_mirror_backend.py +++ b/bots/zephyr_mirror_backend.py @@ -37,39 +37,8 @@ import signal import logging import hashlib import tempfile -import random import select -class CountingBackoff(object): - def __init__(self, maximum_retries=10): - self.number_of_retries = 0 - self.maximum_retries = maximum_retries - - def keep_going(self): - return self.number_of_retries < self.maximum_retries - - def succeed(self): - self.number_of_retries = 0 - - def fail(self): - self.number_of_retries = min(self.number_of_retries + 1, - self.maximum_retries) - -class RandomExponentialBackoff(CountingBackoff): - def fail(self): - self.number_of_retries = min(self.number_of_retries + 1, - self.maximum_retries) - # Exponential growth with ratio sqrt(2); compute random delay - # between x and 2x where x is growing exponentially - delay_scale = int(2 ** (self.number_of_retries / 2.0 - 1)) + 1 - delay = delay_scale + random.randint(1, delay_scale) - message = "Sleeping for %ss [max %s] before retrying." % (delay, delay_scale * 2) - try: - logger.warning(message) - except NameError: - print message - time.sleep(delay) - DEFAULT_SITE = "https://api.zulip.com" class States: @@ -478,7 +447,7 @@ def quit_failed_initialization(message): sys.exit(1) def zephyr_init_autoretry(): - backoff = RandomExponentialBackoff() + backoff = zulip.RandomExponentialBackoff() while backoff.keep_going(): try: # zephyr.init() tries to clear old subscriptions, and thus @@ -493,7 +462,7 @@ def zephyr_init_autoretry(): quit_failed_initialization("Could not initialize Zephyr library, quitting!") def zephyr_load_session_autoretry(session_path): - backoff = RandomExponentialBackoff() + backoff = zulip.RandomExponentialBackoff() while backoff.keep_going(): try: session = file(session_path, "r").read() @@ -508,7 +477,7 @@ def zephyr_load_session_autoretry(session_path): quit_failed_initialization("Could not load saved Zephyr session, quitting!") def zephyr_subscribe_autoretry(sub): - backoff = RandomExponentialBackoff() + backoff = zulip.RandomExponentialBackoff() while backoff.keep_going(): try: zephyr.Subscriptions().add(sub) diff --git a/zulip/__init__.py b/zulip/__init__.py index ce71ef3..92f8b5b 100644 --- a/zulip/__init__.py +++ b/zulip/__init__.py @@ -30,6 +30,7 @@ import os import optparse import platform import urllib +import random from distutils.version import LooseVersion from ConfigParser import SafeConfigParser @@ -46,6 +47,36 @@ requests_json_is_function = callable(requests.Response.json) API_VERSTRING = "v1/" +class CountingBackoff(object): + def __init__(self, maximum_retries=10): + self.number_of_retries = 0 + self.maximum_retries = maximum_retries + + def keep_going(self): + return self.number_of_retries < self.maximum_retries + + def succeed(self): + self.number_of_retries = 0 + + def fail(self): + self.number_of_retries = min(self.number_of_retries + 1, + self.maximum_retries) + +class RandomExponentialBackoff(CountingBackoff): + def fail(self): + self.number_of_retries = min(self.number_of_retries + 1, + self.maximum_retries) + # Exponential growth with ratio sqrt(2); compute random delay + # between x and 2x where x is growing exponentially + delay_scale = int(2 ** (self.number_of_retries / 2.0 - 1)) + 1 + delay = delay_scale + random.randint(1, delay_scale) + message = "Sleeping for %ss [max %s] before retrying." % (delay, delay_scale * 2) + try: + logger.warning(message) + except NameError: + print message + time.sleep(delay) + def _default_client(): return "ZulipPython/" + __version__