Skip to content

Commit

Permalink
Python: add RANDOMKEY command (#1701)
Browse files Browse the repository at this point in the history
* Python: add RANDOMKEY command

* Enable randomkey() test for that redis-rs is fixed

Signed-off-by: Andrew Carbonetto <andrew.carbonetto@improving.com>

* NOP push

Signed-off-by: Andrew Carbonetto <andrew.carbonetto@improving.com>

---------

Signed-off-by: Andrew Carbonetto <andrew.carbonetto@improving.com>
Co-authored-by: Andrew Carbonetto <andrew.carbonetto@improving.com>
  • Loading branch information
aaron-congo and acarbonetto authored Jun 28, 2024
1 parent b231a72 commit 1df349b
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
* Python: Added XGROUP SETID command ([#1683](https://github.com/aws/glide-for-redis/pull/1683))
* Python: Added FUNCTION LOAD command ([#1699](https://github.com/aws/glide-for-redis/pull/1699))
* Python: Added XPENDING command ([#1704](https://github.com/aws/glide-for-redis/pull/1704))
* Python: Added RANDOMKEY command ([#1701](https://github.com/aws/glide-for-redis/pull/1701))

### Breaking Changes
* Node: Update XREAD to return a Map of Map ([#1494](https://github.com/aws/glide-for-redis/pull/1494))
Expand Down
2 changes: 1 addition & 1 deletion glide-core/src/client/standalone_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ impl StandaloneClient {
Some(ResponsePolicy::OneSucceeded) => future::select_ok(requests.map(Box::pin))
.await
.map(|(result, _)| result),
Some(ResponsePolicy::OneSucceededNonEmpty) => {
Some(ResponsePolicy::FirstSucceededNonEmptyOrAllEmpty) => {
future::select_ok(requests.map(|request| {
Box::pin(async move {
let result = request.await?;
Expand Down
5 changes: 2 additions & 3 deletions java/integTest/src/test/java/glide/cluster/CommandTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -1742,9 +1742,8 @@ public void randomKey() {
// no keys in database
assertEquals(OK, clusterClient.flushall(SYNC).get());

// TODO: returns a ResponseError but expecting null
// uncomment when this is completed: https://github.com/amazon-contributing/redis-rs/pull/153
// assertNull(clusterClient.randomKey().get());
// no keys in database returns null
assertNull(clusterClient.randomKey().get());
}

@Test
Expand Down
22 changes: 22 additions & 0 deletions python/python/glide/async_commands/cluster_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -658,3 +658,25 @@ async def lolwut(
TClusterResponse[str],
await self._execute_command(RequestType.Lolwut, args, route),
)

async def random_key(self, route: Optional[Route] = None) -> Optional[str]:
"""
Returns a random existing key name.
See https://valkey.io/commands/randomkey for more details.
Args:
route (Optional[Route]): The command will be routed to all primary nodes, unless `route` is provided,
in which case the client will route the command to the nodes defined by `route`.
Returns:
Optional[str]: A random existing key name.
Examples:
>>> await client.random_key()
"random_key_name" # "random_key_name" is a random existing key name.
"""
return cast(
Optional[str],
await self._execute_command(RequestType.RandomKey, [], route),
)
18 changes: 18 additions & 0 deletions python/python/glide/async_commands/standalone_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,3 +595,21 @@ async def lolwut(
str,
await self._execute_command(RequestType.Lolwut, args),
)

async def random_key(self) -> Optional[str]:
"""
Returns a random existing key name from the currently selected database.
See https://valkey.io/commands/randomkey for more details.
Returns:
Optional[str]: A random existing key name from the currently selected database.
Examples:
>>> await client.random_key()
"random_key_name" # "random_key_name" is a random existing key name from the currently selected database.
"""
return cast(
Optional[str],
await self._execute_command(RequestType.RandomKey, []),
)
11 changes: 11 additions & 0 deletions python/python/glide/async_commands/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -3859,6 +3859,17 @@ def lolwut(
args.extend(str(var))
return self.append_command(RequestType.Lolwut, args)

def random_key(self: TTransaction) -> TTransaction:
"""
Returns a random existing key name.
See https://valkey.io/commands/randomkey for more details.
Command response:
Optional[str]: A random existing key name.
"""
return self.append_command(RequestType.RandomKey, [])


class Transaction(BaseTransaction):
"""
Expand Down
39 changes: 39 additions & 0 deletions python/python/tests/test_async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7003,6 +7003,45 @@ async def test_lolwut(self, redis_client: TGlideClient):
result = await redis_client.lolwut(2, [10, 20], RandomNode())
assert "Redis ver. " in node_result

@pytest.mark.parametrize("cluster_mode", [True])
@pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3])
async def test_cluster_client_random_key(self, redis_client: GlideClusterClient):
key = get_random_string(10)

# setup: delete all keys
assert await redis_client.flushall(FlushMode.SYNC)

# no keys exists, so random_key returns None
assert await redis_client.random_key() is None

assert await redis_client.set(key, "foo") == OK
# `key` should be the only existing key, so random_key should return `key`
assert await redis_client.random_key() == key
assert await redis_client.random_key(AllPrimaries()) == key

@pytest.mark.parametrize("cluster_mode", [False])
@pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3])
async def test_standalone_client_random_key(self, redis_client: GlideClient):
key = get_random_string(10)

# setup: delete all keys in DB 0 and DB 1
assert await redis_client.select(0) == OK
assert await redis_client.flushdb(FlushMode.SYNC) == OK
assert await redis_client.select(1) == OK
assert await redis_client.flushdb(FlushMode.SYNC) == OK

# no keys exist so random_key returns None
assert await redis_client.random_key() is None
# set `key` in DB 1
assert await redis_client.set(key, "foo") == OK
# `key` should be the only key in the database
assert await redis_client.random_key() == key

# switch back to DB 0
assert await redis_client.select(0) == OK
# DB 0 should still have no keys, so random_key should still return None
assert await redis_client.random_key() is None


class TestMultiKeyCommandCrossSlot:
@pytest.mark.parametrize("cluster_mode", [True])
Expand Down
4 changes: 4 additions & 0 deletions python/python/tests/test_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,10 @@ async def transaction_test(
args.append(OK)
transaction.flushdb()
args.append(OK)
transaction.set(key, "foo")
args.append(OK)
transaction.random_key()
args.append(key)

min_version = "6.2.0"
if not await check_if_server_version_lt(redis_client, min_version):
Expand Down

0 comments on commit 1df349b

Please sign in to comment.