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)