github.com/ismailbayram/bigpicture@v0.0.0-20231225173155-e4b21f5efcff/internal/browser/pyproject/base/tasks.py (about) 1 import logging 2 from django.utils.timezone import datetime 3 from django.conf import settings 4 from django.core.cache import cache 5 from django.utils.encoding import force_str 6 7 from washer_project.celery import app 8 9 logger = logging.getLogger(__name__) 10 11 12 class LockTask(app.Task): 13 """this abstract class ensures the same tasks run only once at a time""" 14 abstract = True 15 TTL = getattr(settings, 'DEFAULT_TASK_LOCK_TTL', 60 * 15) 16 17 def __init__(self, *args, **kwargs): 18 super(LockTask, self).__init__(*args, **kwargs) 19 20 def generate_lock_cache_key(self, *args, **kwargs): 21 args_key = [force_str(arg) for arg in args] 22 kwargs_key = ['{}_{}'.format(k, force_str(v)) for k, v in 23 sorted(kwargs.items())] 24 return '_'.join([self.name] + args_key + kwargs_key) 25 26 def __call__(self, *args, **kwargs): 27 """check task""" 28 lock_cache_key = (self.request.headers or {}).pop('cache_key', None) 29 if not lock_cache_key: 30 lock_cache_key = self.generate_lock_cache_key(*args, **kwargs) 31 lock_time = datetime.now().isoformat() 32 lock_acquired = cache.set(lock_cache_key, lock_time, nx=True, 33 timeout=self.TTL) 34 35 if lock_acquired: 36 try: 37 return self.run(*args, **kwargs) 38 finally: 39 cache.delete(lock_cache_key) 40 else: 41 logger.info('Task %s is already running..' % self.name)