tasksets.rst 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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. Callbacks
  21. ---------
  22. Let's improve our ``add`` task so it can accept a callback that
  23. takes the result as an argument::
  24. from celery.decorators import task
  25. from celery.task.sets import subtask
  26. @task
  27. def add(x, y, callback=None):
  28. result = x + y
  29. if callback is not None:
  30. subtask(callback).delay(result)
  31. return result
  32. See? :class:`~celery.task.sets.subtask` also knows how it should be applied,
  33. asynchronously by :meth:`~celery.task.sets.subtask.delay`, and
  34. eagerly by :meth:`~celery.task.sets.subtask.apply`.
  35. The best thing is that any arguments you add to ``subtask.delay``,
  36. will be prepended to the arguments specified by the subtask itself!
  37. So if you have the subtask::
  38. >>> add.subtask(args=(10, ))
  39. ``subtask.delay(result)`` becomes::
  40. >>> add.apply_async(args=(result, 10))
  41. Now let's execute our new ``add`` task with a callback::
  42. >>> add.delay(2, 2, callback=add.subtask((8, )))
  43. As expected this will first launch one task calculating ``2 + 2``, then
  44. another task calculating ``4 + 8``.
  45. Task Sets
  46. =========
  47. The :class:`~celery.task.sets.TaskSet` enables easy invocation of several
  48. tasks at once, and is then able to join the results in the same order as the
  49. tasks were invoked.
  50. The task set works on a list of :class:`~celery.task.sets.subtask`'s::
  51. >>> from celery.task.sets import TaskSet
  52. >>> from tasks import add
  53. >>> job = TaskSet(tasks=[
  54. ... add.subtask((4, 4)),
  55. ... add.subtask((8, 8)),
  56. ... add.subtask((16, 16)),
  57. ... add.subtask((32, 32)),
  58. ... ])
  59. >>> result = job.apply_async()
  60. >>> result.ready() # has all subtasks completed?
  61. True
  62. >>> result.successful() # was all subtasks successful?
  63. >>> result.join()
  64. [4, 8, 16, 32, 64]
  65. Results
  66. -------
  67. When a :class:`~celery.task.sets.TaskSet` is applied it returns a
  68. :class:`~celery.result.TaskSetResult` object.
  69. :class:`~celery.result.TaskSetResult` takes a list of
  70. :class:`~celery.result.AsyncResult` instances and operates on them as if it was a
  71. single task.
  72. It supports the following operations:
  73. * :meth:`~celery.result.TaskSetResult.successful`
  74. Returns :const:`True` if all of the subtasks finished
  75. successfully (e.g. did not raise an exception).
  76. * :meth:`~celery.result.TaskSetResult.failed`
  77. Returns :const:`True` if any of the subtasks failed.
  78. * :meth:`~celery.result.TaskSetResult.waiting`
  79. Returns :const:`True` if any of the subtasks
  80. is not ready.
  81. * :meth:`~celery.result.TaskSetResult.ready`
  82. Return :const:`True` if all of the subtasks
  83. are ready.
  84. * :meth:`~celery.result.TaskSetResult.completed_count`
  85. Returns the number of completed subtasks.
  86. * :meth:`~celery.result.TaskSetResult.revoke`
  87. Revoke all of the subtasks.
  88. * :meth:`~celery.result.TaskSetResult.iterate`
  89. Iterate over the return values of the subtasks
  90. as they finish, one by one.
  91. * :meth:`~celery.result.TaskSetResult.join`
  92. Gather the results for all of the subtasks,
  93. and return a list with them ordered by the order of which they
  94. were called.