import logging from redis import RedisError from redlock import RedLock, RedLockError from app import app logger = logging.getLogger(__name__) class GlobalLock(object): """ A lock object that blocks globally via Redis. Note that Redis is not considered a tier-1 service, so this lock should not be used for any critical code paths. """ def __init__(self, name, lock_ttl=600): self._lock_name = name self._redis_info = dict(app.config['USER_EVENTS_REDIS']) self._redis_info.update({'socket_connect_timeout': 5, 'socket_timeout': 5}) self._lock_ttl = lock_ttl self._redlock = None def __enter__(self): return self.lock() def __exit__(self ,type, value, traceback): self.unlock() def lock(self): logger.debug('Acquiring global lock %s', self._lock_name) try: redlock = RedLock(self._lock_name, connection_details=[self._redis_info], ttl=self._lock_ttl) redlock.acquire() self._redlock = redlock logger.debug('Acquired lock %s', self._lock_name) return True except RedLockError: logger.debug('Could not acquire lock %s', self._lock_name) return False except RedisError as re: logger.debug('Could not connect to Redis for lock %s: %s', self._lock_name, re) return False def unlock(self): if self._redlock is not None: logger.debug('Releasing lock %s', self._lock_name) self._redlock.release() logger.debug('Released lock %s', self._lock_name) self._redlock = None