# Copyright (C) 2015-2024 RhodeCode GmbH # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License, version 3 # (only), as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # # This program is dual-licensed. If you wish to learn more about the # RhodeCode Enterprise Edition, including its added features, Support services, # and proprietary license terms, please see https://rhodecode.com/licenses/ import redis from .._vendor import redis_lock class ArchiveCacheGenerationLock(Exception): pass class GenerationLock: """ Locking mechanism that detects if a lock is acquired with GenerationLock(lock_key): compute_archive() """ lock_timeout = 7200 def __init__(self, lock_key, url): self.lock_key = lock_key self._create_client(url) self.lock = self.get_lock() def _create_client(self, url): connection_pool = redis.ConnectionPool.from_url(url) self.writer_client = redis.StrictRedis( connection_pool=connection_pool ) self.reader_client = self.writer_client def get_lock(self): return redis_lock.Lock( redis_client=self.writer_client, name=self.lock_key, expire=self.lock_timeout, strict=True ) def __enter__(self): acquired = self.lock.acquire(blocking=False) if not acquired: raise ArchiveCacheGenerationLock('Failed to create a lock') def __exit__(self, exc_type, exc_val, exc_tb): self.lock.release()