From e702b196c2f553eea4dbe9f78032010b28d806dd Mon Sep 17 00:00:00 2001 From: Aaron <69273634+aaron-congo@users.noreply.github.com> Date: Tue, 28 May 2024 16:37:37 -0700 Subject: [PATCH 1/2] Python: add OBJECT REFCOUNT command (#317) --- CHANGELOG.md | 1 + python/python/glide/async_commands/core.py | 22 +++++++++++++++++++ .../glide/async_commands/transaction.py | 15 +++++++++++++ python/python/tests/test_async_client.py | 11 ++++++++++ python/python/tests/test_transaction.py | 12 ++++++---- 5 files changed, 57 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5e725883c..73cbf542fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ * Python: Added OBJECT FREQ command ([#1472](https://github.com/aws/glide-for-redis/pull/1472)) * Python: Added OBJECT IDLETIME command ([#1474](https://github.com/aws/glide-for-redis/pull/1474)) * Node: Added RENAMENX command ([#1483](https://github.com/aws/glide-for-redis/pull/1483)) +* Python: Added OBJECT REFCOUNT command ([#1485](https://github.com/aws/glide-for-redis/pull/1485)) ## 0.4.0 (2024-05-26) diff --git a/python/python/glide/async_commands/core.py b/python/python/glide/async_commands/core.py index 0dd027f4f0..5d37e80318 100644 --- a/python/python/glide/async_commands/core.py +++ b/python/python/glide/async_commands/core.py @@ -3587,3 +3587,25 @@ async def object_idletime(self, key: str) -> Optional[int]: Optional[int], await self._execute_command(RequestType.ObjectIdleTime, [key]), ) + + async def object_refcount(self, key: str) -> Optional[int]: + """ + Returns the reference count of the object stored at `key`. + + See https://valkey.io/commands/object-refcount for more details. + + Args: + key (str): The key of the object to get the reference count of. + + Returns: + Optional[int]: If `key` exists, returns the reference count of the object stored at `key` as an integer. + Otherwise, returns None. + + Examples: + >>> await client.object_refcount("my_hash") + 2 # "my_hash" has a reference count of 2. + """ + return cast( + Optional[int], + await self._execute_command(RequestType.ObjectRefCount, [key]), + ) diff --git a/python/python/glide/async_commands/transaction.py b/python/python/glide/async_commands/transaction.py index d16101f92c..4d00ac4375 100644 --- a/python/python/glide/async_commands/transaction.py +++ b/python/python/glide/async_commands/transaction.py @@ -2504,6 +2504,21 @@ def object_idletime(self: TTransaction, key: str) -> TTransaction: """ return self.append_command(RequestType.ObjectIdleTime, [key]) + def object_refcount(self: TTransaction, key: str) -> TTransaction: + """ + Returns the reference count of the object stored at `key`. + + See https://valkey.io/commands/object-refcount for more details. + + Args: + key (str): The key of the object to get the reference count of. + + Command response: + Optional[int]: If `key` exists, returns the reference count of the object stored at `key` as an integer. + Otherwise, returns None. + """ + return self.append_command(RequestType.ObjectRefCount, [key]) + class Transaction(BaseTransaction): """ diff --git a/python/python/tests/test_async_client.py b/python/python/tests/test_async_client.py index 4a2213bf21..88881bfb7c 100644 --- a/python/python/tests/test_async_client.py +++ b/python/python/tests/test_async_client.py @@ -3426,6 +3426,17 @@ async def test_object_idletime(self, redis_client: TRedisClient): idletime = await redis_client.object_idletime(string_key) assert idletime is not None and idletime > 0 + @pytest.mark.parametrize("cluster_mode", [True, False]) + @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) + async def test_object_refcount(self, redis_client: TRedisClient): + string_key = get_random_string(10) + non_existing_key = get_random_string(10) + + assert await redis_client.object_refcount(non_existing_key) is None + assert await redis_client.set(string_key, "foo") == OK + refcount = await redis_client.object_refcount(string_key) + assert refcount is not None and refcount >= 0 + class TestMultiKeyCommandCrossSlot: @pytest.mark.parametrize("cluster_mode", [True]) diff --git a/python/python/tests/test_transaction.py b/python/python/tests/test_transaction.py index f90d336c28..7606cfe8a8 100644 --- a/python/python/tests/test_transaction.py +++ b/python/python/tests/test_transaction.py @@ -518,6 +518,7 @@ async def test_transaction_object_commands( transaction = ClusterTransaction() if cluster_mode else Transaction() transaction.set(string_key, "foo") transaction.object_encoding(string_key) + transaction.object_refcount(string_key) # OBJECT FREQ requires a LFU maxmemory-policy transaction.config_set({maxmemory_policy_key: "allkeys-lfu"}) transaction.object_freq(string_key) @@ -530,14 +531,17 @@ async def test_transaction_object_commands( assert response[0] == OK # transaction.set(string_key, "foo") assert response[1] == "embstr" # transaction.object_encoding(string_key) assert ( - response[2] == OK + cast(int, response[2]) >= 0 + ) # transaction.object_refcount(string_key) + assert ( + response[3] == OK ) # transaction.config_set({maxmemory_policy_key: "allkeys-lfu"}) - assert cast(int, response[3]) >= 0 # transaction.object_freq(string_key) + assert cast(int, response[4]) >= 0 # transaction.object_freq(string_key) assert ( - response[4] == OK + response[5] == OK ) # transaction.config_set({maxmemory_policy_key: "allkeys-random"}) assert ( - cast(int, response[5]) >= 0 + cast(int, response[6]) >= 0 ) # transaction.object_idletime(string_key) finally: await redis_client.config_set({maxmemory_policy_key: maxmemory_policy}) From 26b2f1c796e312d097c4ed275a6c94c47f10c94f Mon Sep 17 00:00:00 2001 From: aaron-congo Date: Wed, 29 May 2024 12:43:38 -0700 Subject: [PATCH 2/2] PR suggestions --- python/python/tests/test_transaction.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/python/python/tests/test_transaction.py b/python/python/tests/test_transaction.py index 7606cfe8a8..160ed6f0f6 100644 --- a/python/python/tests/test_transaction.py +++ b/python/python/tests/test_transaction.py @@ -530,18 +530,14 @@ async def test_transaction_object_commands( assert response is not None assert response[0] == OK # transaction.set(string_key, "foo") assert response[1] == "embstr" # transaction.object_encoding(string_key) - assert ( - cast(int, response[2]) >= 0 - ) # transaction.object_refcount(string_key) - assert ( - response[3] == OK - ) # transaction.config_set({maxmemory_policy_key: "allkeys-lfu"}) + # transaction.object_refcount(string_key) + assert cast(int, response[2]) >= 0 + # transaction.config_set({maxmemory_policy_key: "allkeys-lfu"}) + assert response[3] == OK assert cast(int, response[4]) >= 0 # transaction.object_freq(string_key) - assert ( - response[5] == OK - ) # transaction.config_set({maxmemory_policy_key: "allkeys-random"}) - assert ( - cast(int, response[6]) >= 0 - ) # transaction.object_idletime(string_key) + # transaction.config_set({maxmemory_policy_key: "allkeys-random"}) + assert response[5] == OK + # transaction.object_idletime(string_key) + assert cast(int, response[6]) >= 0 finally: await redis_client.config_set({maxmemory_policy_key: maxmemory_policy})