import functools
import time
import logging


def RetryOnFailure(func):
  """Function decorator to retry on an exception."""

  @functools.wraps(func)
  def Wrapper(*args, **kwargs):
    ratio = 1.5
    wait = 3
    ntries = 0
    start_time = time.time()
    end_time = start_time + 15 * 60
    while time.time() < end_time:
      ntries += 1
      try:
        response = func(*args, **kwargs)
      except Exception as e:
        logging.info(str(e))
        logging.info(
            'Function %s failed, waiting %d seconds, retrying %d ...',
            str(func), wait, ntries)
        time.sleep(wait)
        wait = wait * ratio
      else:
        logging.info(
            'Function %s executed in less then %d sec, with %d tentative(s)',
            str(func), time.time() - start_time, ntries)
        return response
    raise
  return Wrapper