tasksets.rst 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. =======================================
  2. Sets of tasks, Subtasks and Callbacks
  3. =======================================
  4. .. contents::
  5. :local:
  6. Subtasks
  7. ========
  8. The :class:`~celery.task.sets.subtask` class is used to wrap the arguments and
  9. execution options for a single task invocation::
  10. subtask(task_name_or_cls, args, kwargs, options)
  11. For convenience every task also has a shortcut to create subtask instances::
  12. task.subtask(args, kwargs, options)
  13. :class:`~celery.task.sets.subtask` is actually a subclass of :class:`dict`,
  14. which means it can be serialized with JSON or other encodings that doesn't
  15. support complex Python objects.
  16. Also it can be regarded as a type, as the following usage works::
  17. >>> s = subtask("tasks.add", args=(2, 2), kwargs={})
  18. >>> subtask(dict(s)) # coerce dict into subtask
  19. This makes it excellent as a means to pass callbacks around to tasks.
  20. Let's improve our ``add`` task so it can accept a callback that
  21. takes the result as an argument::
  22. from celery.decorators import task
  23. from celery.task.sets import subtask
  24. @task
  25. def add(x, y, callback=None):
  26. result = x + y
  27. if callback is not None:
  28. subtask(callback).apply_async(result)
  29. return result
  30. See? :class:`~celery.task.sets.subtask` also knows how it should be applied,
  31. asynchronously by :meth:`~celery.task.sets.subtask.apply_async`, and
  32. eagerly by :meth:`~celery.task.sets.subtask.apply`.
  33. The best thing is that any arguments you add to ``subtask.apply_async``,
  34. will be prepended to the arguments specified by the subtask itself!
  35. :note: additional keyword arguments will be added to the
  36. execution options, not the task keyword arguments.
  37. So if you have the subtask::
  38. >>> add.subtask(args=(10, ), options={"ignore_result": True})
  39. ``subtask.apply_async(result)`` becomes::
  40. >>> add.apply_async(args=(result, 10), ignore_result=True)
  41. and ``subtask.apply_async(result, ignore_result=False)`` becomes::
  42. >>> add.apply_async(args=(result, 10), ignore_result=False)
  43. Now let's execute our new ``add`` task with a callback::
  44. >>> add.delay(2, 2, callback=add.subtask((8, )))
  45. As expected this will first launch one task calculating ``2 + 2``, then
  46. another task calculating ``4 + 8``.
  47. TaskSets
  48. =========
  49. The :class:`~celery.task.sets.TaskSet` enables easy invocation of several
  50. tasks at once, and is then able to join the results in the same order as the
  51. tasks were invoked.
  52. The task set works on a list of :class:`~celery.task.sets.subtask`'s::
  53. >>> from celery.task.sets import TaskSet
  54. >>> from tasks import add
  55. >>> job = TaskSet(tasks=[
  56. ... add.subtask((4, 4)),
  57. ... add.subtask((8, 8)),
  58. ... add.subtask((16, 16)),
  59. ... add.subtask((32, 32)),
  60. ... ])
  61. >>> result = job.apply_async()
  62. >>> result.ready() # has all subtasks completed?
  63. True
  64. >>> result.successful() # was all subtasks successful?
  65. >>> result.join()
  66. [4, 8, 16, 32, 64]
  67. TaskSet Results
  68. ===============
  69. When a :class:`~celery.task.sets.TaskSet` is applied it returns a
  70. :class:`~celery.result.TaskSetResult` object.
  71. :class:`~celery.result.TaskSetResult` takes a list of
  72. :class:`~celery.result.AsyncResult` instances and operates on them as if it was a
  73. single task.
  74. It supports the following operations:
  75. * :meth:`~celery.result.TaskSetResult.successful`
  76. Returns :const:`True` if all of the subtasks finished
  77. successfully (e.g. did not raise an exception).
  78. * :meth:`~celery.result.TaskSetResult.failed`
  79. Returns :const:`True` if any of the subtasks failed.
  80. * :meth:`~celery.result.TaskSetResult.waiting`
  81. Returns :const:`True` if any of the subtasks
  82. is not ready.
  83. * :meth:`~celery.result.TaskSetResult.ready`
  84. Return :const:`True` if all of the subtasks
  85. are ready.
  86. * :meth:`~celery.result.TaskSetResult.completed_count`
  87. Returns the number of completed subtasks.
  88. * :meth:`~celery.result.TaskSetResult.revoke`
  89. Revoke all of the subtasks.
  90. * :meth:`~celery.result.TaskSetResult.iterate`
  91. Iterate over the return values of the subtasks
  92. as they finish, one by one.
  93. * :meth:`~celery.result.TaskSetResult.join`
  94. Gather the results for all of the subtasks,
  95. and return a list with them ordered by the order of which they
  96. were called.