Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def lock(self, mock_cache):
RedLock._EVENTS = {}
yield RedLock(mock_cache, pytest.KEY, 20)
async def test_multiple_locks_lock(self, mock_cache, lock):
lock_1 = RedLock(mock_cache, pytest.KEY, 20)
lock_2 = RedLock(mock_cache, pytest.KEY, 20)
mock_cache._add.side_effect = [True, ValueError(), ValueError()]
await lock._acquire()
event = lock._EVENTS[pytest.KEY + "-lock"]
assert pytest.KEY + "-lock" in lock._EVENTS
assert pytest.KEY + "-lock" in lock_1._EVENTS
assert pytest.KEY + "-lock" in lock_2._EVENTS
assert not event.is_set()
await asyncio.gather(lock_1._acquire(), lock._release(), lock_2._acquire())
assert pytest.KEY + "-lock" not in lock._EVENTS
assert pytest.KEY + "-lock" not in lock_1._EVENTS
assert pytest.KEY + "-lock" not in lock_2._EVENTS
assert event.is_set()
async def test_calls_redlock(self, decorator, decorator_call):
decorator.cache.get = CoroutineMock(return_value=None)
lock = MagicMock(spec=RedLock)
with patch("aiocache.decorators.RedLock", return_value=lock):
await decorator_call(value="value")
assert decorator.cache.get.call_count == 2
assert lock.__aenter__.call_count == 1
assert lock.__aexit__.call_count == 1
decorator.cache.set.assert_called_with(
"stub()[('value', 'value')]", "value", ttl=SENTINEL
)
stub.assert_called_once_with(value="value")
async def test_calls_locked_client(self, decorator, decorator_call):
decorator.cache.get = CoroutineMock(side_effect=[None, None, None, "value"])
decorator.cache._add = CoroutineMock(side_effect=[True, ValueError])
lock1 = MagicMock(spec=RedLock)
lock2 = MagicMock(spec=RedLock)
with patch("aiocache.decorators.RedLock", side_effect=[lock1, lock2]):
await asyncio.gather(decorator_call(value="value"), decorator_call(value="value"))
assert decorator.cache.get.call_count == 4
assert lock1.__aenter__.call_count == 1
assert lock1.__aexit__.call_count == 1
assert lock2.__aenter__.call_count == 1
assert lock2.__aexit__.call_count == 1
decorator.cache.set.assert_called_with(
"stub()[('value', 'value')]", "value", ttl=SENTINEL
)
assert stub.call_count == 1
async def test_release_wrong_client_fails(self, redis_cache, lock):
wrong_lock = RedLock(redis_cache, pytest.KEY, 20)
await lock.__aenter__()
assert await wrong_lock.__aexit__("exc_type", "exc_value", "traceback") is None
def lock(self, mock_cache):
RedLock._EVENTS = {}
yield RedLock(mock_cache, pytest.KEY, 20)
def lock(cache):
return RedLock(cache, pytest.KEY, 20)
async def test_multiple_locks_lock(self, mock_cache, lock):
lock_1 = RedLock(mock_cache, pytest.KEY, 20)
lock_2 = RedLock(mock_cache, pytest.KEY, 20)
mock_cache._add.side_effect = [True, ValueError(), ValueError()]
await lock._acquire()
event = lock._EVENTS[pytest.KEY + "-lock"]
assert pytest.KEY + "-lock" in lock._EVENTS
assert pytest.KEY + "-lock" in lock_1._EVENTS
assert pytest.KEY + "-lock" in lock_2._EVENTS
assert not event.is_set()
await asyncio.gather(lock_1._acquire(), lock._release(), lock_2._acquire())
assert pytest.KEY + "-lock" not in lock._EVENTS
assert pytest.KEY + "-lock" not in lock_1._EVENTS
assert pytest.KEY + "-lock" not in lock_2._EVENTS
assert event.is_set()
async def decorator(self, f, *args, **kwargs):
key = self.get_cache_key(f, args, kwargs)
value = await self.get_from_cache(key)
if value is not None:
return value
async with RedLock(self.cache, key, self.lease):
value = await self.get_from_cache(key)
if value is not None:
return value
result = await f(*args, **kwargs)
await self.set_in_cache(key, result)
return result
async def _release(self):
removed = await self.client._redlock_release(self.key, self._value)
if removed:
RedLock._EVENTS.pop(self.key).set()