From a26a835747d83d6a1ffad87ae6d49394322696da Mon Sep 17 00:00:00 2001 From: Shoham Elias Date: Sun, 16 Jun 2024 12:51:29 +0000 Subject: [PATCH] Python: adds TOUCH command --- CHANGELOG.md | 1 + python/python/glide/async_commands/core.py | 25 +++++++++++++++++++ .../glide/async_commands/transaction.py | 14 +++++++++++ python/python/tests/test_async_client.py | 12 ++++++++- python/python/tests/test_transaction.py | 2 ++ 5 files changed, 53 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58b4263627..331ea1fee4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ * Node: Added OBJECT IDLETIME command ([#1567](https://github.com/aws/glide-for-redis/pull/1567)) * Node: Added OBJECT REFCOUNT command ([#1568](https://github.com/aws/glide-for-redis/pull/1568)) * Python: Added SETBIT command ([#1571](https://github.com/aws/glide-for-redis/pull/1571)) +* Python: Added TOUCH command ([#1582](https://github.com/aws/glide-for-redis/pull/1582)) ### Breaking Changes * Node: Update XREAD to return a Map of Map ([#1494](https://github.com/aws/glide-for-redis/pull/1494)) diff --git a/python/python/glide/async_commands/core.py b/python/python/glide/async_commands/core.py index 4e33247192..dc51bf680c 100644 --- a/python/python/glide/async_commands/core.py +++ b/python/python/glide/async_commands/core.py @@ -429,6 +429,8 @@ async def set( args.append("GET") if expiry is not None: args.extend(expiry.get_cmd_args()) + + print(args) return cast(Optional[str], await self._execute_command(RequestType.Set, args)) async def get(self, key: str) -> Optional[str]: @@ -795,6 +797,29 @@ async def decrby(self, key: str, amount: int) -> int: int, await self._execute_command(RequestType.DecrBy, [key, str(amount)]) ) + async def touch(self, keys: List[str]) -> int: + """ + Updates the last access time of specified keys. + + See https://valkey.io/commands/touch/ for details. + + Note: + When in cluster mode, the command may route to multiple nodes when `keys` map to different hash slots. + + Args: + keys (List[str]): The keys to update last access time. + + Returns: + int: The number of keys that were updated, a key is ignored is it doesn't exist. + + Examples: + >>> await client.set("myKey1", "value1") + >>> await client.set("myKey2", "value2") + >>> await client.touch(["myKey1", "myKey2", "nonExistentKey"]) + 2 # Last access time of 2 keys has been updated. + """ + return cast(int, await self._execute_command(RequestType.Touch, keys)) + async def hset(self, key: str, field_value_map: Mapping[str, str]) -> int: """ Sets the specified fields to their respective values in the hash stored at `key`. diff --git a/python/python/glide/async_commands/transaction.py b/python/python/glide/async_commands/transaction.py index 743f3e8fe8..6900092c5a 100644 --- a/python/python/glide/async_commands/transaction.py +++ b/python/python/glide/async_commands/transaction.py @@ -345,6 +345,20 @@ def mget(self: TTransaction, keys: List[str]) -> TTransaction: """ return self.append_command(RequestType.MGet, keys) + async def touch(self: TTransaction, keys: List[str]) -> TTransaction: + """ + Updates the last access time of specified keys. + + See https://valkey.io/commands/touch/ for details. + + Args: + keys (List[str]): The keys to update last access time. + + Commands response: + int: The number of keys that were updated, a key is ignored is it doesn't exist. + """ + return self.append_command(RequestType.Touch, keys) + def config_rewrite(self: TTransaction) -> TTransaction: """ Rewrite the configuration file with the current configuration. diff --git a/python/python/tests/test_async_client.py b/python/python/tests/test_async_client.py index 0f94589515..ed0e18ec80 100644 --- a/python/python/tests/test_async_client.py +++ b/python/python/tests/test_async_client.py @@ -548,6 +548,16 @@ async def test_mset_mget(self, redis_client: TRedisClient): keys[-1] = None assert mget_res == keys + @pytest.mark.parametrize("cluster_mode", [True, False]) + @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) + async def test_touch(self, redis_client: TRedisClient): + keys = [get_random_string(10), get_random_string(10)] + key_value_pairs = {key: value for key, value in zip(keys, keys)} + + assert await redis_client.mset(key_value_pairs) == OK + assert await redis_client.touch(keys) == 2 + assert await redis_client.touch([*keys, get_random_string(3)]) == 2 + @pytest.mark.parametrize("cluster_mode", [True, False]) @pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3]) async def test_msetnx(self, redis_client: TRedisClient): @@ -4523,7 +4533,7 @@ async def test_multi_key_command_routed_to_multiple_nodes( await redis_client.delete(["abc", "zxy", "lkn"]) await redis_client.mget(["abc", "zxy", "lkn"]) await redis_client.mset({"abc": "1", "zxy": "2", "lkn": "3"}) - # TODO touch + await redis_client.touch(["abc", "zxy", "lkn"]) class TestCommandsUnitTests: diff --git a/python/python/tests/test_transaction.py b/python/python/tests/test_transaction.py index bd547f6410..68defe1def 100644 --- a/python/python/tests/test_transaction.py +++ b/python/python/tests/test_transaction.py @@ -88,6 +88,8 @@ async def transaction_test( transaction.exists([key2]) args.append(1) + transaction.touch([key2]) + args.append(1) transaction.delete([key2]) args.append(1)