|
@@ -10,6 +10,10 @@ from celery.registry import tasks
|
|
|
from celery.serialization import pickle
|
|
|
|
|
|
|
|
|
+class MaxRetriesExceededError(Exception):
|
|
|
+ """The tasks max restart limit has been exceeded."""
|
|
|
+
|
|
|
+
|
|
|
class Task(object):
|
|
|
"""A task that can be delayed for execution by the ``celery`` daemon.
|
|
|
|
|
@@ -57,6 +61,16 @@ class Task(object):
|
|
|
|
|
|
The message priority. A number from ``0`` to ``9``.
|
|
|
|
|
|
+ .. attribute:: max_retries
|
|
|
+
|
|
|
+ Maximum number of retries before giving up (i.e. raising the last
|
|
|
+ resulting exception). Default is ``3``.
|
|
|
+
|
|
|
+ .. attribute:: default_retry_delay
|
|
|
+
|
|
|
+ Defeault time in seconds before a retry of the task should be
|
|
|
+ executed. Default is a 1 minute delay.
|
|
|
+
|
|
|
.. attribute:: ignore_result
|
|
|
|
|
|
Don't store the status and return value. This means you can't
|
|
@@ -114,6 +128,10 @@ class Task(object):
|
|
|
priority = None
|
|
|
ignore_result = False
|
|
|
disable_error_emails = False
|
|
|
+ max_retries = 3
|
|
|
+ default_retry_delay = 60
|
|
|
+
|
|
|
+ MaxRetriesExceededError = MaxRetriesExceededError
|
|
|
|
|
|
def __init__(self):
|
|
|
if not self.__class__.name:
|
|
@@ -207,6 +225,34 @@ class Task(object):
|
|
|
"""
|
|
|
return apply_async(cls, args, kwargs, **options)
|
|
|
|
|
|
+ def retry(self, args, kwargs, **options):
|
|
|
+ """Retry the task.
|
|
|
+
|
|
|
+ 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)
|
|
|
+
|
|
|
+ """
|
|
|
+ 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)
|
|
|
+ exc = options.pop("exc", MaxRetriesExceededError(
|
|
|
+ "Can't retry %s[%s] args:%s kwargs:%s" % (
|
|
|
+ self.name, options["task_id"], args, kwargs)))
|
|
|
+ if options["retries"] > self.max_retries:
|
|
|
+ raise exc
|
|
|
+ return self.apply_async(args=args, kwargs=kwargs, **options)
|
|
|
+
|
|
|
@classmethod
|
|
|
def apply(cls, args=None, kwargs=None, **options):
|
|
|
"""Execute this task at once, by blocking until the task
|