def renew(self, new_timeout): """ Sets a new timeout for an already acquired lock. ``new_timeout`` can be specified as an integer or a float, both representing the number of seconds. """ if self.local.token is None: raise LockError("Cannot extend an unlocked lock") if self.timeout is None: raise LockError("Cannot extend a lock with no timeout") return self.do_renew(new_timeout)
def __enter__(self): if self.acquire(): return self else: if not self.mute_ex: raise LockError( f"key: {self.name} still locking, please retry it later")
def do_renew(self, new_timeout): pipe = self.redis.pipeline() pipe.watch(self.name) lock_value = pipe.get(self.name) if lock_value != self.local.token: raise LockError("Cannot extend a lock that's no longer owned") pipe.multi() pipe.pexpire(self.name, int(new_timeout * 1000)) try: response = pipe.execute() except WatchError: # someone else acquired the lock raise LockError("Cannot extend a lock that's no longer owned") if not response[0]: # pexpire returns False if the key doesn't exist raise LockError("Cannot extend a lock that's no longer owned") return True
def acquire(self, **kwargs): if not self.__lock_acquired_time: self.__lock_acquired_time = time.time() acquired = self.acquire(**kwargs) wait_time = (time.time() - self.__lock_acquired_time) * 1000 if not acquired: self.__metrics['acquired_fail'] += 1 self.__metrics['wait_{}'.format( self.get_interval_for_time(wait_time))] += 1 raise LockError('Can\'t acquire lock {}'.format(self.name)) self.__metrics['acquired'] += 1 self.__metrics['wait_{}'.format( self.get_interval_for_time(wait_time))] += 1 return True
def __init__(self, redis, name, timeout=None, sleep=0.1): """ Create a new Lock instance named ``name`` using the Redis client supplied by ``redis``. ``timeout`` indicates a maximum life for the lock. By default, it will remain locked until release() is called. ``sleep`` indicates the amount of time to sleep per loop iteration when the lock is in blocking mode and another client is currently holding the lock. Note: If using ``timeout``, you should make sure all the hosts that are running clients have their time synchronized with a network time service like ntp. """ self.redis = redis self.name = name self.acquired_until = None self.timeout = timeout self.sleep = sleep if self.timeout and self.sleep > self.timeout: raise LockError("'sleep' must be less than 'timeout'")
def __enter__(self): if not self.acquire(): raise LockError('Can\'t acquire lock {}'.format(self.name)) return self