Beispiel #1
0
 def test_on_retry(self):
     tw = TaskRequest(mytask.name, uuid(), [1], {"f": "x"})
     tw.eventer = MockEventDispatcher()
     try:
         raise RetryTaskError("foo", KeyError("moofoobar"))
     except:
         einfo = ExceptionInfo(sys.exc_info())
         tw.on_failure(einfo)
         self.assertIn("task-retried", tw.eventer.sent)
Beispiel #2
0
 def test_worker_task_trace_handle_retry(self):
     from celery.exceptions import RetryTaskError
     tid = uuid()
     w = WorkerTaskTrace(mytask.name, tid, [4], {})
     type_, value_, tb_ = self.create_exception(ValueError("foo"))
     type_, value_, tb_ = self.create_exception(
         RetryTaskError(str(value_), exc=value_))
     w._store_errors = False
     w.handle_retry(value_, type_, tb_, "")
     self.assertEqual(mytask.backend.get_status(tid), states.PENDING)
     w._store_errors = True
     w.handle_retry(value_, type_, tb_, "")
     self.assertEqual(mytask.backend.get_status(tid), states.RETRY)
Beispiel #3
0
 def test_worker_task_trace_handle_retry(self):
     from celery.exceptions import RetryTaskError
     tid = uuid()
     mytask.request.update({"id": tid})
     try:
         _, value_, _ = self.create_exception(ValueError("foo"))
         einfo = self.create_exception(
             RetryTaskError(str(value_), exc=value_))
         w = TraceInfo(states.RETRY, einfo[1], einfo)
         w.handle_retry(mytask, store_errors=False)
         self.assertEqual(mytask.backend.get_status(tid), states.PENDING)
         w.handle_retry(mytask, store_errors=True)
         self.assertEqual(mytask.backend.get_status(tid), states.RETRY)
     finally:
         mytask.request.clear()
Beispiel #4
0
 def test_on_retry(self):
     tw = TaskRequest(mytask.name, uuid(), [1], {'f': 'x'}, app=self.app)
     tw.eventer = MockEventDispatcher()
     try:
         raise RetryTaskError('foo', KeyError('moofoobar'))
     except:
         einfo = ExceptionInfo()
         tw.on_failure(einfo)
         self.assertIn('task-retried', tw.eventer.sent)
         prev, module._does_info = module._does_info, False
         try:
             tw.on_failure(einfo)
         finally:
             module._does_info = prev
         einfo.internal = True
         tw.on_failure(einfo)
Beispiel #5
0
 def test_on_retry(self):
     tw = TaskRequest(mytask.name, uuid(), [1], {"f": "x"})
     tw.eventer = MockEventDispatcher()
     try:
         raise RetryTaskError("foo", KeyError("moofoobar"))
     except:
         einfo = ExceptionInfo()
         tw.on_failure(einfo)
         self.assertIn("task-retried", tw.eventer.sent)
         prev, module._does_info = module._does_info, False
         try:
             tw.on_failure(einfo)
         finally:
             module._does_info = prev
         einfo.internal = True
         tw.on_failure(einfo)
Beispiel #6
0
 def test_worker_task_trace_handle_retry(self):
     from celery.exceptions import RetryTaskError
     tid = uuid()
     mytask.request.update({"id": tid})
     try:
         raise ValueError("foo")
     except Exception, exc:
         try:
             raise RetryTaskError(str(exc), exc=exc)
         except RetryTaskError, exc:
             w = TraceInfo(states.RETRY, exc)
             w.handle_retry(mytask, store_errors=False)
             self.assertEqual(mytask.backend.get_status(tid),
                              states.PENDING)
             w.handle_retry(mytask, store_errors=True)
             self.assertEqual(mytask.backend.get_status(tid), states.RETRY)
Beispiel #7
0
 def test_worker_task_trace_handle_retry(self):
     from celery.exceptions import RetryTaskError
     tid = uuid()
     mytask.push_request(id=tid)
     try:
         raise ValueError('foo')
     except Exception as exc:
         try:
             raise RetryTaskError(str(exc), exc=exc)
         except RetryTaskError as exc:
             w = TraceInfo(states.RETRY, exc)
             w.handle_retry(mytask, store_errors=False)
             self.assertEqual(mytask.backend.get_status(tid),
                              states.PENDING)
             w.handle_retry(mytask, store_errors=True)
             self.assertEqual(mytask.backend.get_status(tid), states.RETRY)
     finally:
         mytask.pop_request()
Beispiel #8
0
 def test_trace_RetryTaskError(self):
     exc = RetryTaskError("foo", "bar")
     _, info = trace(raises, (exc, ), {})
     self.assertEqual(info.state, states.RETRY)
     self.assertIs(info.retval, exc)
Beispiel #9
0
 def test_retry_task_error(self):
     try:
         raise Exception('foo')
     except Exception as exc:
         ret = RetryTaskError('Retrying task', exc)
         self.assertEqual(ret.exc, exc)
Beispiel #10
0
 def test_when_datetime(self):
     x = RetryTaskError('foo', KeyError(), when=datetime.utcnow())
     self.assertTrue(x.humanize())
Beispiel #11
0
 def test_retry_task_error(self):
     try:
         raise Exception("foo")
     except Exception, exc:
         ret = RetryTaskError("Retrying task", exc)
Beispiel #12
0
    def retry(self,
              args=None,
              kwargs=None,
              exc=None,
              throw=True,
              eta=None,
              countdown=None,
              max_retries=None,
              **options):
        """Retry the task.

        :param args: Positional arguments to retry with.
        :param kwargs: Keyword arguments to retry with.
        :keyword exc: Optional exception to raise instead of
                      :exc:`~celery.exceptions.MaxRetriesExceededError`
                      when the max restart limit has been exceeded.
        :keyword countdown: Time in seconds to delay the retry for.
        :keyword eta: Explicit time and date to run the retry at
                      (must be a :class:`~datetime.datetime` instance).
        :keyword max_retries: If set, overrides the default retry limit.
        :keyword timeout: If set, overrides the default timeout.
        :keyword soft_timeout: If set, overrides the default soft timeout.
        :keyword \*\*options: Any extra options to pass on to
                              meth:`apply_async`.
        :keyword throw: If this is :const:`False`, do not raise the
                        :exc:`~celery.exceptions.RetryTaskError` exception,
                        that tells the worker to mark the task as being
                        retried.  Note that this means the task will be
                        marked as failed if the task raises an exception,
                        or successful if it returns.

        :raises celery.exceptions.RetryTaskError: To tell the worker that
            the task has been re-sent for retry. This always happens,
            unless the `throw` keyword argument has been explicitly set
            to :const:`False`, and is considered normal operation.

        **Example**

        .. code-block:: python

            >>> @task()
            >>> def tweet(auth, message):
            ...     twitter = Twitter(oauth=auth)
            ...     try:
            ...         twitter.post_status_update(message)
            ...     except twitter.FailWhale as exc:
            ...         # Retry in 5 minutes.
            ...         raise tweet.retry(countdown=60 * 5, exc=exc)

        Although the task will never return above as `retry` raises an
        exception to notify the worker, we use `return` in front of the retry
        to convey that the rest of the block will not be executed.

        """
        request = self.request
        max_retries = self.max_retries if max_retries is None else max_retries
        args = request.args if args is None else args
        kwargs = request.kwargs if kwargs is None else kwargs
        delivery_info = request.delivery_info

        # Not in worker or emulated by (apply/always_eager),
        # so just raise the original exception.
        if request.called_directly:
            maybe_reraise()
            raise exc or RetryTaskError('Task can be retried', None)

        if delivery_info:
            options.setdefault('exchange', delivery_info.get('exchange'))
            options.setdefault('routing_key', delivery_info.get('routing_key'))
        options.setdefault('expires', request.expires)

        if not eta and countdown is None:
            countdown = self.default_retry_delay

        options.update({
            'retries': request.retries + 1,
            'task_id': request.id,
            'countdown': countdown,
            'eta': eta,
            'link': request.callbacks,
            'link_error': request.errbacks
        })

        if max_retries is not None and options['retries'] > max_retries:
            if exc:
                maybe_reraise()
            raise self.MaxRetriesExceededError(
                "Can't retry {0}[{1}] args:{2} kwargs:{3}".format(
                    self.name, options['task_id'], args, kwargs))

        # If task was executed eagerly using apply(),
        # then the retry must also be executed eagerly.
        if request.is_eager:
            self.apply(args=args, kwargs=kwargs, **options).get()
        else:
            self.apply_async(args=args, kwargs=kwargs, **options)
        ret = RetryTaskError(exc=exc, when=eta or countdown)
        if throw:
            raise ret
        return ret
 def test_task_status_retry(self):
     oexc, _ = catch_exception(KeyError("Resource not available"))
     exc, tb = catch_exception(RetryTaskError(str(oexc), oexc))
     self.assertStatusForIs(states.RETRY, exc, tb)
Beispiel #14
0
 def test_pickleable(self):
     x = RetryTaskError('foo', KeyError(), when=datetime.utcnow())
     self.assertTrue(pickle.loads(pickle.dumps(x)))
Beispiel #15
0
 def test_retry_task_error(self):
     try:
         raise Exception("foo")
     except Exception, exc:
         ret = RetryTaskError("Retrying task", exc)
         self.assertEqual(ret.exc, exc)
Beispiel #16
0
    def retry(self, args=None, kwargs=None, exc=None, throw=True,
            eta=None, countdown=None, max_retries=None, **options):
        """Retry the task.

        :param args: Positional arguments to retry with.
        :param kwargs: Keyword arguments to retry with.
        :keyword exc: Optional exception to raise instead of
                      :exc:`~celery.exceptions.MaxRetriesExceededError`
                      when the max restart limit has been exceeded.
        :keyword countdown: Time in seconds to delay the retry for.
        :keyword eta: Explicit time and date to run the retry at
                      (must be a :class:`~datetime.datetime` instance).
        :keyword max_retries: If set, overrides the default retry limit.
        :keyword \*\*options: Any extra options to pass on to
                              meth:`apply_async`.
        :keyword throw: If this is :const:`False`, do not raise the
                        :exc:`~celery.exceptions.RetryTaskError` exception,
                        that tells the worker to mark the task as being
                        retried.  Note that this means the task will be
                        marked as failed if the task raises an exception,
                        or successful if it returns.

        :raises celery.exceptions.RetryTaskError: To tell the worker that
            the task has been re-sent for retry. This always happens,
            unless the `throw` keyword argument has been explicitly set
            to :const:`False`, and is considered normal operation.

        **Example**

        .. code-block:: python

            >>> @task
            >>> def tweet(auth, message):
            ...     twitter = Twitter(oauth=auth)
            ...     try:
            ...         twitter.post_status_update(message)
            ...     except twitter.FailWhale, exc:
            ...         # Retry in 5 minutes.
            ...         return tweet.retry(countdown=60 * 5, exc=exc)

        Although the task will never return above as `retry` raises an
        exception to notify the worker, we use `return` in front of the retry
        to convey that the rest of the block will not be executed.

        """
        request = self.request
        if max_retries is None:
            max_retries = self.max_retries
        if args is None:
            args = request.args
        if kwargs is None:
            kwargs = request.kwargs
        delivery_info = request.delivery_info

        if delivery_info:
            options.setdefault("exchange", delivery_info.get("exchange"))
            options.setdefault("routing_key", delivery_info.get("routing_key"))

        if not eta and countdown is None:
            countdown = self.default_retry_delay

        options.update({"retries": request.retries + 1,
                        "task_id": request.id,
                        "countdown": countdown,
                        "eta": eta})

        if max_retries is not None and options["retries"] > max_retries:
            raise exc or self.MaxRetriesExceededError(
                            "Can't retry %s[%s] args:%s kwargs:%s" % (
                                self.name, options["task_id"], args, kwargs))

        # If task was executed eagerly using apply(),
        # then the retry must also be executed eagerly.
        if request.is_eager:
            return self.apply(args=args, kwargs=kwargs, **options).get()

        self.apply_async(args=args, kwargs=kwargs, **options)
        if throw:
            raise RetryTaskError(
                eta and "Retry at %s" % (eta, )
                     or "Retry in %s secs." % (countdown, ), exc)
Beispiel #17
0
    def retry(self,
              args=None,
              kwargs=None,
              exc=None,
              throw=True,
              eta=None,
              countdown=None,
              max_retries=None,
              **options):
        """Retry the task.

        :param args: Positional arguments to retry with.
        :param kwargs: Keyword arguments to retry with.
        :keyword exc: Custom exception to report when the max restart
            limit has been exceeded (default:
            :exc:`~celery.exceptions.MaxRetriesExceededError`).

            If this argument is set and retry is called while
            an exception was raised (``sys.exc_info()`` is set)
            it will attempt to reraise the current exception.

            If no exception was raised it will raise the ``exc``
            argument provided.
        :keyword countdown: Time in seconds to delay the retry for.
        :keyword eta: Explicit time and date to run the retry at
                      (must be a :class:`~datetime.datetime` instance).
        :keyword max_retries: If set, overrides the default retry limit.
        :keyword \*\*options: Any extra options to pass on to
                              meth:`apply_async`.
        :keyword throw: If this is :const:`False`, do not raise the
                        :exc:`~celery.exceptions.RetryTaskError` exception,
                        that tells the worker to mark the task as being
                        retried.  Note that this means the task will be
                        marked as failed if the task raises an exception,
                        or successful if it returns.

        :raises celery.exceptions.RetryTaskError: To tell the worker that
            the task has been re-sent for retry. This always happens,
            unless the `throw` keyword argument has been explicitly set
            to :const:`False`, and is considered normal operation.

        **Example**

        .. code-block:: python

            >>> @task()
            >>> def tweet(auth, message):
            ...     twitter = Twitter(oauth=auth)
            ...     try:
            ...         twitter.post_status_update(message)
            ...     except twitter.FailWhale, exc:
            ...         # Retry in 5 minutes.
            ...         raise tweet.retry(countdown=60 * 5, exc=exc)

        Although the task will never return above as `retry` raises an
        exception to notify the worker, we use `return` in front of the retry
        to convey that the rest of the block will not be executed.

        """
        request = self.request
        retries = request.retries + 1
        max_retries = self.max_retries if max_retries is None else max_retries

        # Not in worker or emulated by (apply/always_eager),
        # so just raise the original exception.
        if request.called_directly:
            maybe_reraise()  # raise orig stack if PyErr_Occurred
            raise exc or RetryTaskError('Task can be retried', None)

        if not eta and countdown is None:
            countdown = self.default_retry_delay

        S = self.subtask_from_request(request,
                                      args,
                                      kwargs,
                                      countdown=countdown,
                                      eta=eta,
                                      retries=retries,
                                      **options)

        if max_retries is not None and retries > max_retries:
            if exc:
                maybe_reraise()
            raise self.MaxRetriesExceededError(
                """Can't retry %s[%s] args:%s kwargs:%s""" %
                (self.name, request.id, S.args, S.kwargs))

        # If task was executed eagerly using apply(),
        # then the retry must also be executed eagerly.
        S.apply().get() if request.is_eager else S.apply_async()
        ret = RetryTaskError(exc=exc, when=eta or countdown)
        if throw:
            raise ret
        return ret
Beispiel #18
0
    def retry(self, args=None, kwargs=None, exc=None, throw=True, **options):
        """Retry the task.

        :param args: Positional arguments to retry with.
        :param kwargs: Keyword arguments to retry with.
        :keyword exc: Optional exception to raise instead of
            :exc:`~celery.exceptions.MaxRetriesExceededError` when the max
            restart limit has been exceeded.
        :keyword countdown: Time in seconds to delay the retry for.
        :keyword eta: Explicit time and date to run the retry at (must be a
            :class:`datetime.datetime` instance).
        :keyword \*\*options: Any extra options to pass on to
            meth:`apply_async`. See :func:`celery.execute.apply_async`.
        :keyword throw: If this is ``False``, do not raise the
            :exc:`~celery.exceptions.RetryTaskError` exception,
            that tells the worker to mark the task as being retried.
            Note that this means the task will be marked as failed
            if the task raises an exception, or successful if it
            returns.

        :raises celery.exceptions.RetryTaskError: To tell the worker that the
            task has been re-sent for retry. This always happens, unless
            the ``throw`` keyword argument has been explicitly set
            to ``False``, and is considered normal operation.

        Example

            >>> class TwitterPostStatusTask(Task):
            ...
            ...     def run(self, username, password, message, **kwargs):
            ...         twitter = Twitter(username, password)
            ...         try:
            ...             twitter.post_status(message)
            ...         except twitter.FailWhale, exc:
            ...             # Retry in 5 minutes.
            ...             self.retry([username, password, message], kwargs,
            ...                        countdown=60 * 5, exc=exc)

        """
        if not kwargs:
            raise TypeError(
                    "kwargs argument to retries can't be empty. "
                    "Task must accept **kwargs, see http://bit.ly/cAx3Bg")

        delivery_info = kwargs.pop("delivery_info", {})
        options.setdefault("exchange", delivery_info.get("exchange"))
        options.setdefault("routing_key", delivery_info.get("routing_key"))

        options["retries"] = kwargs.pop("task_retries", 0) + 1
        options["task_id"] = kwargs.pop("task_id", None)
        options["countdown"] = options.get("countdown",
                                           self.default_retry_delay)
        max_exc = exc or self.MaxRetriesExceededError(
                "Can't retry %s[%s] args:%s kwargs:%s" % (
                    self.name, options["task_id"], args, kwargs))
        max_retries = self.max_retries
        if max_retries is not None and options["retries"] > max_retries:
            raise max_exc

        # If task was executed eagerly using apply(),
        # then the retry must also be executed eagerly.
        if kwargs.get("task_is_eager", False):
            result = self.apply(args=args, kwargs=kwargs, **options)
            if isinstance(result, EagerResult):
                return result.get()                 # propogates exceptions.
            return result

        self.apply_async(args=args, kwargs=kwargs, **options)

        if throw:
            message = "Retry in %d seconds." % options["countdown"]
            raise RetryTaskError(message, exc)