|
@@ -5,8 +5,12 @@ Asynchronous result types.
|
|
|
"""
|
|
|
from celery.backends import default_backend
|
|
|
from celery.datastructures import PositionQueue
|
|
|
-from celery.timer import TimeoutTimer
|
|
|
from itertools import imap
|
|
|
+import threading
|
|
|
+
|
|
|
+
|
|
|
+class TimeoutError(Exception):
|
|
|
+ """The operation timed out."""
|
|
|
|
|
|
|
|
|
class BaseAsyncResult(object):
|
|
@@ -28,6 +32,8 @@ class BaseAsyncResult(object):
|
|
|
|
|
|
"""
|
|
|
|
|
|
+ TimeoutError = TimeoutError
|
|
|
+
|
|
|
def __init__(self, task_id, backend):
|
|
|
self.task_id = task_id
|
|
|
self.backend = backend
|
|
@@ -50,7 +56,7 @@ class BaseAsyncResult(object):
|
|
|
:keyword timeout: How long to wait in seconds, before the
|
|
|
operation times out.
|
|
|
|
|
|
- :raises celery.timer.TimeoutError: if ``timeout`` is not ``None`` and
|
|
|
+ :raises TimeoutError: if ``timeout`` is not ``None`` and
|
|
|
the result does not arrive within ``timeout`` seconds.
|
|
|
|
|
|
If the remote call raised an exception then that
|
|
@@ -253,7 +259,7 @@ class TaskSetResult(object):
|
|
|
:keyword timeout: The time in seconds, how long
|
|
|
it will wait for results, before the operation times out.
|
|
|
|
|
|
- :raises celery.timer.TimeoutError: if ``timeout`` is not ``None``
|
|
|
+ :raises TimeoutError: if ``timeout`` is not ``None``
|
|
|
and the operation takes longer than ``timeout`` seconds.
|
|
|
|
|
|
If any of the tasks raises an exception, the exception
|
|
@@ -262,23 +268,28 @@ class TaskSetResult(object):
|
|
|
:returns: list of return values for all tasks in the taskset.
|
|
|
|
|
|
"""
|
|
|
- timeout_timer = TimeoutTimer(timeout)
|
|
|
- results = PositionQueue(length=self.total)
|
|
|
|
|
|
- while True:
|
|
|
- for position, pending_result in enumerate(self.subtasks):
|
|
|
- if pending_result.status == "DONE":
|
|
|
- results[position] = pending_result.result
|
|
|
- elif pending_result.status == "FAILURE":
|
|
|
- raise pending_result.result
|
|
|
- if results.full():
|
|
|
- # Make list copy, so the returned type is not a position
|
|
|
- # queue.
|
|
|
- return list(results)
|
|
|
+ def on_timeout():
|
|
|
+ raise TimeoutError("The operation timed out.")
|
|
|
|
|
|
- # This raises TimeoutError when timed out.
|
|
|
- timeout_timer.tick()
|
|
|
+ timeout_timer = threading.Timer(timeout, on_timeout)
|
|
|
+ results = PositionQueue(length=self.total)
|
|
|
|
|
|
+ timeout_timer.start()
|
|
|
+ try:
|
|
|
+ while True:
|
|
|
+ for position, pending_result in enumerate(self.subtasks):
|
|
|
+ if pending_result.status == "DONE":
|
|
|
+ results[position] = pending_result.result
|
|
|
+ elif pending_result.status == "FAILURE":
|
|
|
+ raise pending_result.result
|
|
|
+ if results.full():
|
|
|
+ # Make list copy, so the returned type is not a position
|
|
|
+ # queue.
|
|
|
+ return list(results)
|
|
|
+ finally:
|
|
|
+ timeout_timer.cancel()
|
|
|
+
|
|
|
@property
|
|
|
def total(self):
|
|
|
"""The total number of tasks in the :class:`celery.task.TaskSet`."""
|