def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except self.exception_tuple as e: # match on `caused_by` if self.caused_by_tuple is None or isinstance(e, WrapperException) and isinstance(e.caused_by, self.caused_by_tuple): # get self reference -> get subclass of RetryableTask cur_task = args[0] # use exponential backoff for retrying retry_time = CeleryUtil.exp_backoff(cur_task, self.max_retry_time) # log error Util.log_will_retry(retry_time, exc = e, what = func.__name__) # retry raise cur_task.retry(args = cur_task.get_retry_arguments(), exc = e, max_retries = self.max_retries, countdown = retry_time ) # no match on exceptions -> no retry! -> propagate exception raise e, None, sys.exc_info()[2]