75 lines
1.9 KiB
Python
75 lines
1.9 KiB
Python
import sys
|
|
import eventlet
|
|
import contexter
|
|
import six
|
|
|
|
|
|
class Task(object):
|
|
@classmethod
|
|
def get_or_create(cls, signal, kwargs=None, logger=None):
|
|
if not hasattr(cls, '_registry'):
|
|
cls._registry = []
|
|
|
|
task = cls(signal, kwargs, logger=logger)
|
|
|
|
if task not in cls._registry:
|
|
cls._registry.append(task)
|
|
|
|
return cls._registry[cls._registry.index(task)]
|
|
|
|
def __init__(self, signal, kwargs=None, logger=None):
|
|
self.signal = signal
|
|
self.kwargs = kwargs or {}
|
|
self.logger = logger
|
|
self.failures = 0
|
|
self.task_semaphore = eventlet.semaphore.BoundedSemaphore(1)
|
|
|
|
def __call__(self, semaphores=None):
|
|
semaphores = semaphores or []
|
|
|
|
with contexter.Contexter(self.task_semaphore, *semaphores):
|
|
result = self._do()
|
|
|
|
if result:
|
|
self.failures = 0
|
|
else:
|
|
self.failures += 1
|
|
|
|
return result
|
|
|
|
def _do(self):
|
|
try:
|
|
self._emit()
|
|
except Exception:
|
|
self._exception(*sys.exc_info())
|
|
return False
|
|
else:
|
|
self._completed()
|
|
return True
|
|
finally:
|
|
self._clean()
|
|
|
|
def _clean(self):
|
|
pass
|
|
|
|
def _completed(self):
|
|
if self.logger:
|
|
self.logger.info('[%s] Completed' % self)
|
|
|
|
def _exception(self, e_type, e_value, e_traceback):
|
|
if self.logger:
|
|
self.logger.exception('[%s] Raised exception: %s' % (
|
|
self, e_value))
|
|
else:
|
|
six.reraise(e_type, e_value, e_traceback)
|
|
|
|
def _emit(self):
|
|
if self.logger:
|
|
self.logger.info('[%s] Running' % self)
|
|
self.signal.emit(**self.kwargs)
|
|
|
|
def __eq__(self, other):
|
|
return (self.signal == other.signal and self.kwargs == other.kwargs)
|
|
|
|
def __str__(self):
|
|
return '%s: %s' % (self.signal.__class__.__name__, self.kwargs)
|