Exemplo n.º 1
0
        def wrapper(*args, **kwargs):
            next_interval = self.retry_interval
            remaining = self.max_retries

            while True:
                try:
                    return f(*args, **kwargs)
                except Exception as e:
                    with excutils.save_and_reraise_exception() as ectxt:
                        if remaining > 0:
                            ectxt.reraise = not self._is_exception_expected(e)
                        else:
                            LOG.exception('DB exceeded retry limit.')
                            # if it's a RetryRequest, we need to unpack it
                            if isinstance(e, exceptions.RetryRequest):
                                ectxt.type_ = type(e.inner_exc)
                                ectxt.value = e.inner_exc
                    LOG.debug("Performing DB retry for function %s",
                              reflection.get_callable_name(f))
                    # NOTE(vsergeyev): We are using patched time module, so
                    #                  this effectively yields the execution
                    #                  context to another green thread.
                    time.sleep(next_interval)
                    if self.inc_retry_interval:
                        next_interval = min(next_interval * 2,
                                            self.max_retry_interval)
                    remaining -= 1
Exemplo n.º 2
0
    def __init__(self,
                 functor,
                 requires,
                 name=None,
                 provides=None,
                 auto_extract=True,
                 rebind=None,
                 inject=None):

        if not six.callable(functor):
            raise ValueError("Function to use for map must be callable")

        f_args = reflection.get_callable_args(functor)
        if len(f_args) != 1:
            raise ValueError("%s arguments were provided. Map functor must "
                             "take exactly 1 argument." % len(f_args))

        if not misc.is_iterable(requires):
            raise TypeError("%s type was provided for requires. Requires "
                            "must be an iterable." % type(requires))

        if name is None:
            name = reflection.get_callable_name(functor)
        super(MapFunctorTask, self).__init__(name=name,
                                             provides=provides,
                                             inject=inject,
                                             requires=requires,
                                             rebind=rebind,
                                             auto_extract=auto_extract)

        self._functor = functor
Exemplo n.º 3
0
def safe_func_wrapper(f, logger=None):
    try:
        f()
    except Exception as e:
        if logger:
            logger.error(
                'function %s error: %s' %
                (reflection.get_callable_name(f), e.__class__.__name__))
            if hasattr(logger, 'exception'):
                logger.exception('Safe error traceback')
Exemplo n.º 4
0
 def _idle_for(result, elapsed):
     delay = round(elapsed - interval, 2)
     if delay > 0:
         func_name = reflection.get_callable_name(self.f)
         LOG.warning(
             'Function %(func_name)r run outlasted '
             'interval by %(delay).2f sec', {
                 'func_name': func_name,
                 'delay': delay
             })
     return -delay if delay < 0 else 0
Exemplo n.º 5
0
def _fetch_validate_factory(flow_factory):
    if isinstance(flow_factory, six.string_types):
        factory_fun = _fetch_factory(flow_factory)
        factory_name = flow_factory
    else:
        factory_fun = flow_factory
        factory_name = reflection.get_callable_name(flow_factory)
        try:
            reimported = _fetch_factory(factory_name)
            assert reimported == factory_fun
        except (ImportError, AssertionError):
            raise ValueError('Flow factory %r is not reimportable by name %s' %
                             (factory_fun, factory_name))
    return factory_name, factory_fun
Exemplo n.º 6
0
    def __call__(self, f):
        func_name = reflection.get_callable_name(f)

        def _func(*args, **kwargs):
            result = None
            try:
                if self._retry_count:
                    LOG.debug(
                        "Invoking %(func_name)s; retry count is "
                        "%(retry_count)d.", {
                            'func_name': func_name,
                            'retry_count': self._retry_count
                        })
                result = f(*args, **kwargs)
            except self._exceptions:
                with excutils.save_and_reraise_exception() as ctxt:
                    LOG.debug(
                        "Exception which is in the suggested list of "
                        "exceptions occurred while invoking function:"
                        " %s.", func_name)
                    if (self._max_retry_count != -1
                            and self._retry_count >= self._max_retry_count):
                        LOG.debug(
                            "Cannot retry %(func_name)s upon "
                            "suggested exception "
                            "since retry count (%(retry_count)d) "
                            "reached max retry count "
                            "(%(max_retry_count)d).", {
                                'retry_count': self._retry_count,
                                'max_retry_count': self._max_retry_count,
                                'func_name': func_name
                            })
                    else:
                        ctxt.reraise = False
                        self._retry_count += 1
                        self._sleep_time += self._inc_sleep_time
                        return self._sleep_time
            raise LoopingCallDone(result)

        @six.wraps(f)
        def func(*args, **kwargs):
            loop = DynamicLoopingCall(_func, *args, **kwargs)
            evt = loop.start(periodic_interval_max=self._max_sleep_time)
            LOG.debug("Waiting for function %s to return.", func_name)
            return evt.wait()

        return func
Exemplo n.º 7
0
 def _run_loop(self,
               idle_for_func,
               initial_delay=None,
               stop_on_exception=True):
     kind = self._KIND
     func_name = reflection.get_callable_name(self.f)
     func = self.f if stop_on_exception else _safe_wrapper(
         self.f, kind, func_name)
     if initial_delay:
         greenthread.sleep(initial_delay)
     try:
         watch = timeutils.StopWatch()
         while self._running:
             watch.restart()
             result = func(*self.args, **self.kw)
             watch.stop()
             if not self._running:
                 break
             idle = idle_for_func(result, watch.elapsed())
             LOG.trace(
                 '%(kind)s %(func_name)r sleeping '
                 'for %(idle).02f seconds', {
                     'func_name': func_name,
                     'idle': idle,
                     'kind': kind
                 })
             greenthread.sleep(idle)
     except LoopingCallDone as e:
         self.done.send(e.retvalue)
     except Exception:
         exc_info = sys.exc_info()
         try:
             LOG.error('%(kind)s %(func_name)r failed', {
                 'kind': kind,
                 'func_name': func_name
             },
                       exc_info=exc_info)
             self.done.send_exception(*exc_info)
         finally:
             del exc_info
         return
     else:
         self.done.send(True)
Exemplo n.º 8
0
    def __init__(self,
                 execute,
                 name=None,
                 provides=None,
                 requires=None,
                 auto_extract=True,
                 rebind=None,
                 revert=None,
                 version=None,
                 inject=None):
        if not six.callable(execute):
            raise ValueError("Function to use for executing must be"
                             " callable")
        if revert is not None:
            if not six.callable(revert):
                raise ValueError("Function to use for reverting must"
                                 " be callable")
        if name is None:
            name = reflection.get_callable_name(execute)
        super(FunctorTask, self).__init__(name,
                                          provides=provides,
                                          inject=inject)
        self._execute = execute
        self._revert = revert
        if version is not None:
            self.version = version
        mapping = self._build_arg_mapping(execute, requires, rebind,
                                          auto_extract)
        self.rebind, exec_requires, self.optional = mapping

        if revert:
            revert_mapping = self._build_arg_mapping(revert, requires, rebind,
                                                     auto_extract)
        else:
            revert_mapping = (self.rebind, exec_requires, self.optional)
        (self.revert_rebind, revert_requires,
         self.revert_optional) = revert_mapping
        self.requires = exec_requires.union(revert_requires)