def __call__(self, difference, old_val, new_val): kwargs = {} kwargs.update(self.extra_kwargs) kwargs["record"] = self.record kwargs["callback_id"] = self.callback_id kwargs["difference"] = difference kwargs["changes"] = self.record._convert_diff_to_changelist( difference, old_val, new_val ) logger.debug(f"Firing callback {self.callback} with kwargs: {kwargs}") # trim down the passed parameters # to include only those the callback will accept params = signature(self.callback).parameters if not any(["**" in str(p) for p in params.values()]): # there's no "**kwargs" in the callback signature, # so remove any unaccepted params for arg in kwargs.keys(): if arg not in params: del kwargs[arg] # perform the callback, gracefully handling any exceptions try: # trigger the callback within its own thread, # so it won't block others if it's long-running Thread(target=self.callback, kwargs=kwargs, daemon=True).start() except Exception as e: logger.error( f"Error while processing callback for {repr(self.record)}: {repr(e)}" )
def poll_forever(self): """ Call `poll()` in never-ending loop with small time intervals in-between. This function is blocking, it never returns! """ while True: try: self.poll() except Exception as e: logger.error("Encountered error during polling!") logger.error(e, exc_info=True) time.sleep(1)
def poll(self, retries: int = 10): """ Poll for changes. Arguments --------- retries : int, optional Number of times to retry request if it fails. Defaults to 10. Raises ------ HTTPError When GET request fails for `retries` times. """ logger.debug("Starting new long-poll request") while retries: try: response = self.client.session.get(self.url(EIO=3, sid=self.sid)) response.raise_for_status() retries -= 1 except HTTPError as e: try: message = f"{response.content} / {e}" except AttributeError: message = str(e) logger.warn( f"Problem with submitting poll request: {message} (will retry {retries} more times)" ) time.sleep(0.1) if retries <= 0: raise if retries <= 5: logger.error( f"Persistent error submitting poll request: {message} (will retry {retries} more times)" ) # if we're close to giving up, also try reinitializing the session self.initialize() self._refresh_updated_records( self._decode_numbered_json_thing(response.content) )
def __init__(self, message: str, **extra): dumped_data = json.dumps(extra, indent=2) logger.error(f"Exception: {dumped_data}") super().__init__(message)