def __init__(self): self.on_active_breakpoints_changed = lambda x: None self.on_idle = lambda: None self._debuggee_labels = {} self._service_account_auth = False self._debuggee_id = None self._wait_token = 'init' self._breakpoints = [] self._main_thread = None self._transmission_thread = None self._transmission_thread_startup_lock = threading.Lock() self._transmission_queue = deque(maxlen=100) self._new_updates = threading.Event(False) # Disable logging in the discovery API to avoid excessive logging. class _ChildLogFilter(logging.Filter): """Filter to eliminate info-level logging when called from this module.""" def __init__(self, filter_levels=None): super(_ChildLogFilter, self).__init__() self._filter_levels = filter_levels or set(logging.INFO) # Get name without extension to avoid .py vs .pyc issues self._my_filename = os.path.splitext( inspect.getmodule(_ChildLogFilter).__file__)[0] def filter(self, record): if record.levelno not in self._filter_levels: return True callerframes = inspect.getouterframes(inspect.currentframe()) for f in callerframes: if os.path.splitext(f[1])[0] == self._my_filename: return False return True self._log_filter = _ChildLogFilter({logging.INFO}) discovery.logger.addFilter(self._log_filter) # # Configuration options (constants only modified by unit test) # # Delay before retrying failed request. self.register_backoff = Backoff() # Register debuggee. self.list_backoff = Backoff() # Query active breakpoints. self.update_backoff = Backoff() # Update breakpoint. # Maximum number of times that the message is re-transmitted before it # is assumed to be poisonous and discarded self.max_transmit_attempts = 10
def test_custom_max_backoff(self): now = time.time() _backoff = Backoff(max_backoff=7200) _backoff.backoff_time = 4096 _backoff._bump_backoff() self.assertEqual(7200, _backoff.backoff_time)
def test_max_backoff(self): now = time.time() _backoff = Backoff() _backoff.backoff_time = 3600 _backoff._bump_backoff() self.assertEqual(3600, _backoff.backoff_time)
def test_raises_in_backoff(self): _backoff = Backoff() @_backoff def foo(a): raise Exception self._call_and_toss_exception(foo, 1) self.assertRaises(InBackoff, foo, 1)
def test_raises_exception(self): _backoff = Backoff() @_backoff def foo(a): raise Exception self._call_and_toss_exception(foo, 1) self.assertEqual(2, _backoff.backoff_time)
def test_reset(self): _backoff = Backoff() now = time.time() _backoff.start_time = now - 3 _backoff.backoff_time = 2 @_backoff def foo(): pass foo() self.assertEqual(None, _backoff.backoff_time) self.assertEqual(None, _backoff.start_time)
def test_backoff_elapsed(self): _backoff = Backoff() @_backoff def foo(a=None): if a is None: raise Exception return a self._call_and_toss_exception(foo) now = time.time() _backoff.start_time = now - 2 self.assertEqual(1, foo(1))
def test_backoff_elapsed_raises_again(self): _backoff = Backoff() @_backoff def foo(a=None): if a is None: raise Exception return a self._call_and_toss_exception(foo) now = time.time() _backoff.start_time = now - 2 self.assertRaises(Exception, foo) self.assertEqual(4, _backoff.backoff_time)
def main(interval=10, restart_in_progress=False, restart_errors=False, restart_all=False, no_update_state=False, log_level='DEBUG', one_pass=False): backdoor(6666) class Stop(BaseException): pass logging.basicConfig(level=log_level) jobs = gevent.pool.Pool(MAX_JOBS) backoff = Backoff(1, 60) try: while True: try: sheet = open_sheet(CONFIG['sheet_id'], CONFIG['worksheet_title'], CONFIG['creds']) backoff.reset() while True: start_jobs(jobs, sheet, restart_in_progress=restart_in_progress, restart_errors=restart_errors, restart_all=restart_all, no_update_state=no_update_state) if one_pass: raise Stop restart_in_progress = False # restart in progress on first pass only (if at all) restart_all = False gevent.sleep(interval) except Exception: logging.exception("Main loop failure") gevent.sleep(backoff.get()) except KeyboardInterrupt: logging.warning("Interrupt recieved") jobs.kill(block=True) except Stop: pass logging.info("Waiting for {} jobs".format(len(jobs.greenlets))) jobs.join()