|  | @@ -1,5 +1,7 @@
 | 
											
												
													
														|  | 
 |  | +import time
 | 
											
												
													
														|  | 
 |  | +from collections import deque
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  from celery.task.base import Task
 |  |  from celery.task.base import Task
 | 
											
												
													
														|  | -from celery.task.builtins import PingTask
 |  | 
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  class CoroutineTask(Task):
 |  |  class CoroutineTask(Task):
 | 
											
										
											
												
													
														|  | @@ -29,25 +31,37 @@ class Aggregate(CoroutineTask):
 | 
											
												
													
														|  |      abstract = True
 |  |      abstract = True
 | 
											
												
													
														|  |      proxied = None
 |  |      proxied = None
 | 
											
												
													
														|  |      minlen = 100
 |  |      minlen = 100
 | 
											
												
													
														|  | 
 |  | +    time_max = 60
 | 
											
												
													
														|  | 
 |  | +    _time_since = None
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      def body(self):
 |  |      def body(self):
 | 
											
												
													
														|  | -        waiting = []
 |  | 
 | 
											
												
													
														|  | 
 |  | +        waiting = deque()
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +        timesince = time.time()
 | 
											
												
													
														|  |          while True:
 |  |          while True:
 | 
											
												
													
														|  |              argtuple = (yield)
 |  |              argtuple = (yield)
 | 
											
												
													
														|  |              waiting.append(argtuple)
 |  |              waiting.append(argtuple)
 | 
											
												
													
														|  | -            if len(waiting) >= self.minlen:
 |  | 
 | 
											
												
													
														|  | -                res = []
 |  | 
 | 
											
												
													
														|  | -                for task_args, task_kwargs in waiting:
 |  | 
 | 
											
												
													
														|  | -                    try:
 |  | 
 | 
											
												
													
														|  | -                        res.append(self.proxied(*args, **kwargs))
 |  | 
 | 
											
												
													
														|  | -                    except Exception, exc:
 |  | 
 | 
											
												
													
														|  | -                        pass # TODO handle errors here, please
 |  | 
 | 
											
												
													
														|  | -                yield res
 |  | 
 | 
											
												
													
														|  | 
 |  | +            if self._expired() or len(waiting) >= self.minlen:
 | 
											
												
													
														|  | 
 |  | +                yield self.process(waiting)
 | 
											
												
													
														|  | 
 |  | +                waiting.clear()
 | 
											
												
													
														|  |              else:
 |  |              else:
 | 
											
												
													
														|  |                  yield None
 |  |                  yield None
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +    def process(self, jobs):
 | 
											
												
													
														|  | 
 |  | +        """Jobs is a deque with the arguments gathered so far.
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        Arguments is a args, kwargs tuple.
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        """
 | 
											
												
													
														|  | 
 |  | +        raise NotImplementedError(
 | 
											
												
													
														|  | 
 |  | +                "Subclasses of Aggregate needs to implement process()")
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    def _expired(self):
 | 
											
												
													
														|  | 
 |  | +        if not self._time_since:
 | 
											
												
													
														|  | 
 |  | +            self._time_since = time.time()
 | 
											
												
													
														|  | 
 |  | +            return False
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -class AggregatePing(Aggregate):
 |  | 
 | 
											
												
													
														|  | -    proxied = PingTask
 |  | 
 | 
											
												
													
														|  | -    n = 100
 |  | 
 | 
											
												
													
														|  | 
 |  | +        if time.time() + self.time_max > self._time_since:
 | 
											
												
													
														|  | 
 |  | +            self._time_since = time.time()
 | 
											
												
													
														|  | 
 |  | +            return True
 | 
											
												
													
														|  | 
 |  | +        return False
 |