diff --git a/django_valkey/base.py b/django_valkey/base.py index 915fce9..fb40e08 100644 --- a/django_valkey/base.py +++ b/django_valkey/base.py @@ -210,6 +210,9 @@ def set(self: BaseValkeyCache, *args, **kwargs) -> bool: def incr_version(self: BaseValkeyCache, *args, **kwargs) -> int: return self.client.incr_version(*args, **kwargs) + def decr_version(self: BaseValkeyCache, *args, **kwargs) -> int: + return self.client.decr_version(*args, **kwargs) + def add(self: BaseValkeyCache, *args, **kwargs) -> bool: return self.client.add(*args, **kwargs) @@ -398,6 +401,9 @@ async def set(self: BaseValkeyCache, *args, **kwargs): async def incr_version(self, *args, **kwargs): return await self.client.aincr_version(*args, **kwargs) + async def decr_version(self, *args, **kwargs): + return await self.client.adecr_version(*args, **kwargs) + async def add(self, *args, **kwargs): return await self.client.aadd(*args, **kwargs) diff --git a/django_valkey/base_client.py b/django_valkey/base_client.py index 7770f12..b457b9b 100644 --- a/django_valkey/base_client.py +++ b/django_valkey/base_client.py @@ -331,6 +331,15 @@ def incr_version( self.delete(old_key, client=client) return version + delta + def decr_version( + self: BaseClient, + key: KeyT, + delta: int = 1, + version: int | None = None, + client: Backend | Any | None = None, + ) -> int: + return self.incr_version(key=key, delta=-delta, version=version, client=client) + def _incr_version( self: BaseClient, key: KeyT, @@ -1464,6 +1473,17 @@ async def incr_version( await self.delete(old_key, client=client) return version + delta + async def decr_version( + self: BaseClient, + key: KeyT, + delta: int = 1, + version: int | None = None, + client: Backend | Any | None = None, + ) -> int: + return await self.incr_version( + key=key, delta=-delta, version=version, client=client + ) + async def _incr_version(self, key, delta, version, client) -> tuple: if version is None: version = self._backend.version diff --git a/tests/test_backend.py b/tests/test_backend.py index d99d626..ffebabb 100644 --- a/tests/test_backend.py +++ b/tests/test_backend.py @@ -536,6 +536,28 @@ def test_ttl_incr_version_no_timeout(self, cache: ValkeyCache): assert my_value == "hello world!" + def test_decr_version(self, cache: ValkeyCache): + cache.set("keytest", 2, version=3) + res = cache.get("keytest", version=3) + assert res == 2 + + cache.decr_version("keytest", version=3) + + res = cache.get("keytest", version=3) + assert res is None + + res = cache.get("keytest", version=2) + assert res == 2 + + def test_ttl_decr_version_no_timeout(self, cache: ValkeyCache): + cache.set("my_key", "hello world!", version=3, timeout=None) + + cache.decr_version("my_key", version=3) + + my_value = cache.get("my_key", version=2) + + assert my_value == "hello world!" + def test_delete_pattern(self, cache: ValkeyCache): if isinstance(cache.client, DefaultClusterClient): pytest.skip("cluster client has a specific test") diff --git a/tests/test_cache_options.py b/tests/test_cache_options.py index ddfcc45..ecdaf21 100644 --- a/tests/test_cache_options.py +++ b/tests/test_cache_options.py @@ -36,6 +36,7 @@ def reverse_key(key: str) -> str: "hlen", "incr", "incr_version", + "decr_version", "keys", "lock", "mget", diff --git a/tests/tests_async/test_backend.py b/tests/tests_async/test_backend.py index 86002b1..1fddb2e 100644 --- a/tests/tests_async/test_backend.py +++ b/tests/tests_async/test_backend.py @@ -516,6 +516,28 @@ async def test_ttl_incr_version_no_timeout(self, cache: AsyncValkeyCache): assert my_value == "hello world!" + async def test_decr_version(self, cache: AsyncValkeyCache): + await cache.aset("keytest", 2, version=3) + res = await cache.aget("keytest", version=3) + assert res == 2 + + await cache.decr_version("keytest", version=3) + + res = await cache.aget("keytest", version=3) + assert res is None + + res = await cache.aget("keytest", version=2) + assert res == 2 + + async def test_ttl_decr_version_no_timeout(self, cache: AsyncValkeyCache): + await cache.set("my_key", "hello world!", timeout=None, version=3) + + await cache.adecr_version("my_key", version=3) + + my_value = await cache.get("my_key", version=2) + + assert my_value == "hello world!" + async def test_delete_pattern(self, cache: AsyncValkeyCache): for key in ["foo-aa", "foo-ab", "foo-bb", "foo-bc"]: await cache.aset(key, "foo") diff --git a/tests/tests_async/test_cache_options.py b/tests/tests_async/test_cache_options.py index 7f48e77..a2ee600 100644 --- a/tests/tests_async/test_cache_options.py +++ b/tests/tests_async/test_cache_options.py @@ -30,6 +30,7 @@ "hlen", "incr", "incr_version", + "decr_version", "keys", "lock", "mget",