|  | @@ -1,11 +1,82 @@
 | 
	
		
			
				|  |  | +import sys
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +from time import time
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  from eventlet import GreenPool
 | 
	
		
			
				|  |  | -from eventlet import spawn
 | 
	
		
			
				|  |  | +from eventlet.greenthread import spawn, spawn_after_local
 | 
	
		
			
				|  |  | +from greenlet import GreenletExit
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  from celery.concurrency.base import apply_target, BasePool
 | 
	
		
			
				|  |  | +from celery.utils import timer2
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class Schedule(timer2.Schedule):
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def __init__(self, *args, **kwargs):
 | 
	
		
			
				|  |  | +        super(Schedule, self).__init__(*args, **kwargs)
 | 
	
		
			
				|  |  | +        self._queue = set()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def enter(self, entry, eta=None, priority=0):
 | 
	
		
			
				|  |  | +        try:
 | 
	
		
			
				|  |  | +            timer2.to_timestamp(eta)
 | 
	
		
			
				|  |  | +        except OverflowError:
 | 
	
		
			
				|  |  | +            if not self.handle_error(sys.exc_info()):
 | 
	
		
			
				|  |  | +                raise
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        now = time()
 | 
	
		
			
				|  |  | +        if eta is None:
 | 
	
		
			
				|  |  | +            eta = now
 | 
	
		
			
				|  |  | +        secs = eta - now
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        g = spawn_after_local(secs, entry)
 | 
	
		
			
				|  |  | +        self._queue.add(g)
 | 
	
		
			
				|  |  | +        g.link(self._entry_exit, entry)
 | 
	
		
			
				|  |  | +        g.entry = entry
 | 
	
		
			
				|  |  | +        g.eta = eta
 | 
	
		
			
				|  |  | +        g.priority = priority
 | 
	
		
			
				|  |  | +        g.cancelled = False
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return g
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def _entry_exit(self, g, entry):
 | 
	
		
			
				|  |  | +        try:
 | 
	
		
			
				|  |  | +            try:
 | 
	
		
			
				|  |  | +                g.wait()
 | 
	
		
			
				|  |  | +            except GreenletExit:
 | 
	
		
			
				|  |  | +                entry.cancel()
 | 
	
		
			
				|  |  | +                g.cancelled = True
 | 
	
		
			
				|  |  | +        finally:
 | 
	
		
			
				|  |  | +            self._queue.discard(g)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def clear(self):
 | 
	
		
			
				|  |  | +        queue = self._queue
 | 
	
		
			
				|  |  | +        while queue:
 | 
	
		
			
				|  |  | +            try:
 | 
	
		
			
				|  |  | +                queue.pop().cancel()
 | 
	
		
			
				|  |  | +            except KeyError:
 | 
	
		
			
				|  |  | +                pass
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @property
 | 
	
		
			
				|  |  | +    def queue(self):
 | 
	
		
			
				|  |  | +        return [(g.eta, g.priority, g.entry) for g in self._queue]
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class Timer(timer2.Timer):
 | 
	
		
			
				|  |  | +    Schedule = Schedule
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def ensure_started(self):
 | 
	
		
			
				|  |  | +        pass
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def stop(self):
 | 
	
		
			
				|  |  | +        self.schedule.clear()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def start(self):
 | 
	
		
			
				|  |  | +        pass
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  class TaskPool(BasePool):
 | 
	
		
			
				|  |  |      Pool = GreenPool
 | 
	
		
			
				|  |  | +    Timer = Timer
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      signal_safe = False
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -31,3 +102,5 @@ class TaskPool(BasePool):
 | 
	
		
			
				|  |  |          eventlet.monkey_patch()
 | 
	
		
			
				|  |  |          eventlet.debug.hub_prevent_multiple_readers(False)
 | 
	
		
			
				|  |  |  TaskPool.on_import()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 |