From 10be2797569d1fd6d9dbe99edcbf6ae2638e31b8 Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Mon, 17 Jun 2024 09:10:59 -0700 Subject: [PATCH 1/4] Java: Add `FLUSHDB` command. (#366) * Add `FLUSHDB` command. Signed-off-by: Yury-Fridlyand * Address PR comments. Signed-off-by: Yury-Fridlyand --------- Signed-off-by: Yury-Fridlyand --- glide-core/src/protobuf/redis_request.proto | 1 + glide-core/src/request_type.rs | 3 + .../src/main/java/glide/api/RedisClient.java | 12 +++ .../java/glide/api/RedisClusterClient.java | 25 ++++++ .../ServerManagementClusterCommands.java | 64 ++++++++++++++ .../commands/ServerManagementCommands.java | 28 +++++++ .../glide/api/models/BaseTransaction.java | 25 ++++++ .../glide/api/models/commands/FlushMode.java | 9 +- .../test/java/glide/api/RedisClientTest.java | 42 ++++++++++ .../glide/api/RedisClusterClientTest.java | 83 +++++++++++++++++++ .../glide/api/models/TransactionTests.java | 5 ++ .../java/glide/TransactionTestUtilities.java | 4 + .../test/java/glide/cluster/CommandTests.java | 22 ++++- .../java/glide/standalone/CommandTests.java | 18 +++- 14 files changed, 336 insertions(+), 5 deletions(-) diff --git a/glide-core/src/protobuf/redis_request.proto b/glide-core/src/protobuf/redis_request.proto index 38de7099c7..663ce757c5 100644 --- a/glide-core/src/protobuf/redis_request.proto +++ b/glide-core/src/protobuf/redis_request.proto @@ -202,6 +202,7 @@ enum RequestType { Sort = 160; FunctionKill = 161; FunctionStats = 162; + FlushDB = 164; LSet = 165; XDel = 166; XRange = 167; diff --git a/glide-core/src/request_type.rs b/glide-core/src/request_type.rs index 03287d5e62..5b9fd47d84 100644 --- a/glide-core/src/request_type.rs +++ b/glide-core/src/request_type.rs @@ -172,6 +172,7 @@ pub enum RequestType { Sort = 160, FunctionKill = 161, FunctionStats = 162, + FlushDB = 164, LSet = 165, XDel = 166, XRange = 167, @@ -361,6 +362,7 @@ impl From<::protobuf::EnumOrUnknown> for RequestType { ProtobufRequestType::XLen => RequestType::XLen, ProtobufRequestType::FunctionKill => RequestType::FunctionKill, ProtobufRequestType::FunctionStats => RequestType::FunctionStats, + ProtobufRequestType::FlushDB => RequestType::FlushDB, ProtobufRequestType::LSet => RequestType::LSet, ProtobufRequestType::XDel => RequestType::XDel, ProtobufRequestType::XRange => RequestType::XRange, @@ -547,6 +549,7 @@ impl RequestType { RequestType::XLen => Some(cmd("XLEN")), RequestType::FunctionKill => Some(get_two_word_command("FUNCTION", "KILL")), RequestType::FunctionStats => Some(get_two_word_command("FUNCTION", "STATS")), + RequestType::FlushDB => Some(cmd("FLUSHDB")), RequestType::LSet => Some(cmd("LSET")), RequestType::XDel => Some(cmd("XDEL")), RequestType::XRange => Some(cmd("XRANGE")), diff --git a/java/client/src/main/java/glide/api/RedisClient.java b/java/client/src/main/java/glide/api/RedisClient.java index f4a6057844..2386a6261e 100644 --- a/java/client/src/main/java/glide/api/RedisClient.java +++ b/java/client/src/main/java/glide/api/RedisClient.java @@ -18,6 +18,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.DBSize; import static redis_request.RedisRequestOuterClass.RequestType.Echo; import static redis_request.RedisRequestOuterClass.RequestType.FlushAll; +import static redis_request.RedisRequestOuterClass.RequestType.FlushDB; import static redis_request.RedisRequestOuterClass.RequestType.FunctionDelete; import static redis_request.RedisRequestOuterClass.RequestType.FunctionFlush; import static redis_request.RedisRequestOuterClass.RequestType.FunctionKill; @@ -172,6 +173,17 @@ public CompletableFuture flushall(@NonNull FlushMode mode) { FlushAll, new String[] {mode.toString()}, this::handleStringResponse); } + @Override + public CompletableFuture flushdb() { + return commandManager.submitNewCommand(FlushDB, new String[0], this::handleStringResponse); + } + + @Override + public CompletableFuture flushdb(@NonNull FlushMode mode) { + return commandManager.submitNewCommand( + FlushDB, new String[] {mode.toString()}, this::handleStringResponse); + } + @Override public CompletableFuture lolwut() { return commandManager.submitNewCommand(Lolwut, new String[0], this::handleStringResponse); diff --git a/java/client/src/main/java/glide/api/RedisClusterClient.java b/java/client/src/main/java/glide/api/RedisClusterClient.java index 5b7e7f5a16..af2958cbba 100644 --- a/java/client/src/main/java/glide/api/RedisClusterClient.java +++ b/java/client/src/main/java/glide/api/RedisClusterClient.java @@ -20,6 +20,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.Echo; import static redis_request.RedisRequestOuterClass.RequestType.FCall; import static redis_request.RedisRequestOuterClass.RequestType.FlushAll; +import static redis_request.RedisRequestOuterClass.RequestType.FlushDB; import static redis_request.RedisRequestOuterClass.RequestType.FunctionDelete; import static redis_request.RedisRequestOuterClass.RequestType.FunctionFlush; import static redis_request.RedisRequestOuterClass.RequestType.FunctionKill; @@ -342,6 +343,30 @@ public CompletableFuture flushall( FlushAll, new String[] {mode.toString()}, route, this::handleStringResponse); } + @Override + public CompletableFuture flushdb() { + return commandManager.submitNewCommand(FlushDB, new String[0], this::handleStringResponse); + } + + @Override + public CompletableFuture flushdb(@NonNull FlushMode mode) { + return commandManager.submitNewCommand( + FlushDB, new String[] {mode.toString()}, this::handleStringResponse); + } + + @Override + public CompletableFuture flushdb(@NonNull SingleNodeRoute route) { + return commandManager.submitNewCommand( + FlushDB, new String[0], route, this::handleStringResponse); + } + + @Override + public CompletableFuture flushdb( + @NonNull FlushMode mode, @NonNull SingleNodeRoute route) { + return commandManager.submitNewCommand( + FlushDB, new String[] {mode.toString()}, route, this::handleStringResponse); + } + @Override public CompletableFuture lolwut() { return commandManager.submitNewCommand(Lolwut, new String[0], this::handleStringResponse); diff --git a/java/client/src/main/java/glide/api/commands/ServerManagementClusterCommands.java b/java/client/src/main/java/glide/api/commands/ServerManagementClusterCommands.java index edfd1cd5d7..23767d6db7 100644 --- a/java/client/src/main/java/glide/api/commands/ServerManagementClusterCommands.java +++ b/java/client/src/main/java/glide/api/commands/ServerManagementClusterCommands.java @@ -382,6 +382,70 @@ public interface ServerManagementClusterCommands { */ CompletableFuture flushall(FlushMode mode, SingleNodeRoute route); + /** + * Deletes all the keys of the currently selected database. This command never fails.
+ * The command will be routed to all primary nodes. + * + * @see valkey.io for details. + * @return OK. + * @example + *
{@code
+     * String response = client.flushdb().get();
+     * assert response.equals("OK");
+     * }
+ */ + CompletableFuture flushdb(); + + /** + * Deletes all the keys of the currently selected database. This command never fails.
+ * The command will be routed to all primary nodes. + * + * @see valkey.io for details. + * @param mode The flushing mode, could be either {@link FlushMode#SYNC} or {@link + * FlushMode#ASYNC}. + * @return OK. + * @example + *
{@code
+     * String response = client.flushdb(ASYNC).get();
+     * assert response.equals("OK");
+     * }
+ */ + CompletableFuture flushdb(FlushMode mode); + + /** + * Deletes all the keys of the currently selected database. This command never fails. + * + * @see valkey.io for details. + * @param route Specifies the routing configuration for the command. The client will route the + * command to the nodes defined by route. + * @return OK. + * @example + *
{@code
+     * Route route = new SlotKeyRoute("key", PRIMARY);
+     * String response = client.flushdb(route).get();
+     * assert response.equals("OK");
+     * }
+ */ + CompletableFuture flushdb(SingleNodeRoute route); + + /** + * Deletes all the keys of the currently selected database. This command never fails. + * + * @see valkey.io for details. + * @param mode The flushing mode, could be either {@link FlushMode#SYNC} or {@link + * FlushMode#ASYNC}. + * @param route Specifies the routing configuration for the command. The client will route the + * command to the nodes defined by route. + * @return OK. + * @example + *
{@code
+     * Route route = new SlotKeyRoute("key", PRIMARY);
+     * String response = client.flushdb(SYNC, route).get();
+     * assert response.equals("OK");
+     * }
+ */ + CompletableFuture flushdb(FlushMode mode, SingleNodeRoute route); + /** * Displays a piece of generative computer art and the Redis version.
* The command will be routed to a random node. diff --git a/java/client/src/main/java/glide/api/commands/ServerManagementCommands.java b/java/client/src/main/java/glide/api/commands/ServerManagementCommands.java index d59568eb73..b38b46564f 100644 --- a/java/client/src/main/java/glide/api/commands/ServerManagementCommands.java +++ b/java/client/src/main/java/glide/api/commands/ServerManagementCommands.java @@ -180,6 +180,34 @@ public interface ServerManagementCommands { */ CompletableFuture flushall(FlushMode mode); + /** + * Deletes all the keys of the currently selected database. This command never fails. + * + * @see valkey.io for details. + * @return OK. + * @example + *
{@code
+     * String response = client.flushdb().get();
+     * assert response.equals("OK");
+     * }
+ */ + CompletableFuture flushdb(); + + /** + * Deletes all the keys of the currently selected database. This command never fails. + * + * @see valkey.io for details. + * @param mode The flushing mode, could be either {@link FlushMode#SYNC} or {@link + * FlushMode#ASYNC}. + * @return OK. + * @example + *
{@code
+     * String response = client.flushdb(ASYNC).get();
+     * assert response.equals("OK");
+     * }
+ */ + CompletableFuture flushdb(FlushMode mode); + /** * Displays a piece of generative computer art and the Redis version. * diff --git a/java/client/src/main/java/glide/api/models/BaseTransaction.java b/java/client/src/main/java/glide/api/models/BaseTransaction.java index c0ad83c79c..9554b994dc 100644 --- a/java/client/src/main/java/glide/api/models/BaseTransaction.java +++ b/java/client/src/main/java/glide/api/models/BaseTransaction.java @@ -52,6 +52,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.ExpireTime; import static redis_request.RedisRequestOuterClass.RequestType.FCall; import static redis_request.RedisRequestOuterClass.RequestType.FlushAll; +import static redis_request.RedisRequestOuterClass.RequestType.FlushDB; import static redis_request.RedisRequestOuterClass.RequestType.FunctionDelete; import static redis_request.RedisRequestOuterClass.RequestType.FunctionFlush; import static redis_request.RedisRequestOuterClass.RequestType.FunctionList; @@ -2947,6 +2948,30 @@ public T flushall(FlushMode mode) { return getThis(); } + /** + * Deletes all the keys of the currently selected database. This command never fails. + * + * @see valkey.io for details. + * @return Command Response - OK. + */ + public T flushdb() { + protobufTransaction.addCommands(buildCommand(FlushDB)); + return getThis(); + } + + /** + * Deletes all the keys of the currently selected database. This command never fails. + * + * @see valkey.io for details. + * @param mode The flushing mode, could be either {@link FlushMode#SYNC} or {@link + * FlushMode#ASYNC}. + * @return Command Response - OK. + */ + public T flushdb(FlushMode mode) { + protobufTransaction.addCommands(buildCommand(FlushDB, buildArgs(mode.toString()))); + return getThis(); + } + /** * Displays a piece of generative computer art and the Redis version. * diff --git a/java/client/src/main/java/glide/api/models/commands/FlushMode.java b/java/client/src/main/java/glide/api/models/commands/FlushMode.java index 69fc260ecd..1594ba733a 100644 --- a/java/client/src/main/java/glide/api/models/commands/FlushMode.java +++ b/java/client/src/main/java/glide/api/models/commands/FlushMode.java @@ -14,6 +14,9 @@ *
  • FLUSHALL command implemented by {@link RedisClient#flushall(FlushMode)}, * {@link RedisClusterClient#flushall(FlushMode)}, and {@link * RedisClusterClient#flushall(FlushMode, SingleNodeRoute)}. + *
  • FLUSHDB command implemented by {@link RedisClient#flushdb(FlushMode)}, {@link + * RedisClusterClient#flushdb(FlushMode)}, and {@link RedisClusterClient#flushdb(FlushMode, + * SingleNodeRoute)}. *
  • FUNCTION FLUSH command implemented by {@link * RedisClient#functionFlush(FlushMode)}, {@link RedisClusterClient#functionFlush(FlushMode)}, * and {@link RedisClusterClient#functionFlush(FlushMode, Route)}. @@ -23,7 +26,11 @@ * href="https://valkey.io/commands/function-flush/">valkey.io */ public enum FlushMode { - /** Flushes synchronously. */ + /** + * Flushes synchronously. + * + * @since Redis 6.2 and above. + */ SYNC, /** Flushes asynchronously. */ ASYNC diff --git a/java/client/src/test/java/glide/api/RedisClientTest.java b/java/client/src/test/java/glide/api/RedisClientTest.java index b5184a76cb..97fd2aaab0 100644 --- a/java/client/src/test/java/glide/api/RedisClientTest.java +++ b/java/client/src/test/java/glide/api/RedisClientTest.java @@ -84,6 +84,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.ExpireTime; import static redis_request.RedisRequestOuterClass.RequestType.FCall; import static redis_request.RedisRequestOuterClass.RequestType.FlushAll; +import static redis_request.RedisRequestOuterClass.RequestType.FlushDB; import static redis_request.RedisRequestOuterClass.RequestType.FunctionDelete; import static redis_request.RedisRequestOuterClass.RequestType.FunctionFlush; import static redis_request.RedisRequestOuterClass.RequestType.FunctionKill; @@ -4422,6 +4423,47 @@ public void flushall_with_mode_returns_success() { assertEquals(OK, payload); } + @SneakyThrows + @Test + public void flushdb_returns_success() { + // setup + CompletableFuture testResponse = new CompletableFuture<>(); + testResponse.complete(OK); + + // match on protobuf request + when(commandManager.submitNewCommand(eq(FlushDB), eq(new String[0]), any())) + .thenReturn(testResponse); + + // exercise + CompletableFuture response = service.flushdb(); + String payload = response.get(); + + // verify + assertEquals(testResponse, response); + assertEquals(OK, payload); + } + + @SneakyThrows + @Test + public void flushdb_with_mode_returns_success() { + // setup + CompletableFuture testResponse = new CompletableFuture<>(); + testResponse.complete(OK); + + // match on protobuf request + when(commandManager.submitNewCommand( + eq(FlushDB), eq(new String[] {SYNC.toString()}), any())) + .thenReturn(testResponse); + + // exercise + CompletableFuture response = service.flushdb(SYNC); + String payload = response.get(); + + // verify + assertEquals(testResponse, response); + assertEquals(OK, payload); + } + @SneakyThrows @Test public void lolwut_returns_success() { diff --git a/java/client/src/test/java/glide/api/RedisClusterClientTest.java b/java/client/src/test/java/glide/api/RedisClusterClientTest.java index 6ed9c5111c..c6d5143f48 100644 --- a/java/client/src/test/java/glide/api/RedisClusterClientTest.java +++ b/java/client/src/test/java/glide/api/RedisClusterClientTest.java @@ -28,6 +28,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.Echo; import static redis_request.RedisRequestOuterClass.RequestType.FCall; import static redis_request.RedisRequestOuterClass.RequestType.FlushAll; +import static redis_request.RedisRequestOuterClass.RequestType.FlushDB; import static redis_request.RedisRequestOuterClass.RequestType.FunctionDelete; import static redis_request.RedisRequestOuterClass.RequestType.FunctionFlush; import static redis_request.RedisRequestOuterClass.RequestType.FunctionKill; @@ -918,6 +919,88 @@ public void flushall_with_route_and_mode_returns_success() { assertEquals(OK, payload); } + @SneakyThrows + @Test + public void flushdb_returns_success() { + // setup + CompletableFuture testResponse = new CompletableFuture<>(); + testResponse.complete(OK); + + // match on protobuf request + when(commandManager.submitNewCommand(eq(FlushDB), eq(new String[0]), any())) + .thenReturn(testResponse); + + // exercise + CompletableFuture response = service.flushdb(); + String payload = response.get(); + + // verify + assertEquals(testResponse, response); + assertEquals(OK, payload); + } + + @SneakyThrows + @Test + public void flushdb_with_mode_returns_success() { + // setup + CompletableFuture testResponse = new CompletableFuture<>(); + testResponse.complete(OK); + + // match on protobuf request + when(commandManager.submitNewCommand( + eq(FlushDB), eq(new String[] {SYNC.toString()}), any())) + .thenReturn(testResponse); + + // exercise + CompletableFuture response = service.flushdb(SYNC); + String payload = response.get(); + + // verify + assertEquals(testResponse, response); + assertEquals(OK, payload); + } + + @SneakyThrows + @Test + public void flushdb_with_route_returns_success() { + // setup + CompletableFuture testResponse = new CompletableFuture<>(); + testResponse.complete(OK); + + // match on protobuf request + when(commandManager.submitNewCommand(eq(FlushDB), eq(new String[0]), eq(RANDOM), any())) + .thenReturn(testResponse); + + // exercise + CompletableFuture response = service.flushdb(RANDOM); + String payload = response.get(); + + // verify + assertEquals(testResponse, response); + assertEquals(OK, payload); + } + + @SneakyThrows + @Test + public void flushdb_with_route_and_mode_returns_success() { + // setup + CompletableFuture testResponse = new CompletableFuture<>(); + testResponse.complete(OK); + + // match on protobuf request + when(commandManager.submitNewCommand( + eq(FlushDB), eq(new String[] {SYNC.toString()}), eq(RANDOM), any())) + .thenReturn(testResponse); + + // exercise + CompletableFuture response = service.flushdb(SYNC, RANDOM); + String payload = response.get(); + + // verify + assertEquals(testResponse, response); + assertEquals(OK, payload); + } + @SneakyThrows @Test public void lolwut_returns_success() { diff --git a/java/client/src/test/java/glide/api/models/TransactionTests.java b/java/client/src/test/java/glide/api/models/TransactionTests.java index f92a9710d5..455708f5ca 100644 --- a/java/client/src/test/java/glide/api/models/TransactionTests.java +++ b/java/client/src/test/java/glide/api/models/TransactionTests.java @@ -64,6 +64,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.ExpireTime; import static redis_request.RedisRequestOuterClass.RequestType.FCall; import static redis_request.RedisRequestOuterClass.RequestType.FlushAll; +import static redis_request.RedisRequestOuterClass.RequestType.FlushDB; import static redis_request.RedisRequestOuterClass.RequestType.FunctionDelete; import static redis_request.RedisRequestOuterClass.RequestType.FunctionFlush; import static redis_request.RedisRequestOuterClass.RequestType.FunctionList; @@ -748,6 +749,10 @@ InfScoreBound.NEGATIVE_INFINITY, new ScoreBoundary(3, false), new Limit(1, 2)), results.add(Pair.of(FlushAll, buildArgs())); results.add(Pair.of(FlushAll, buildArgs(ASYNC.toString()))); + transaction.flushdb().flushdb(ASYNC); + results.add(Pair.of(FlushDB, buildArgs())); + results.add(Pair.of(FlushDB, buildArgs(ASYNC.toString()))); + transaction.lolwut().lolwut(5).lolwut(new int[] {1, 2}).lolwut(6, new int[] {42}); results.add(Pair.of(Lolwut, buildArgs())); results.add(Pair.of(Lolwut, buildArgs(VERSION_REDIS_API, "5"))); diff --git a/java/integTest/src/test/java/glide/TransactionTestUtilities.java b/java/integTest/src/test/java/glide/TransactionTestUtilities.java index 0f3008dbec..08716b7ec1 100644 --- a/java/integTest/src/test/java/glide/TransactionTestUtilities.java +++ b/java/integTest/src/test/java/glide/TransactionTestUtilities.java @@ -656,6 +656,8 @@ private static Object[] serverManagementCommands(BaseTransaction transaction) .lolwut(1) .flushall() .flushall(ASYNC) + .flushdb() + .flushdb(ASYNC) .dbsize(); return new Object[] { @@ -665,6 +667,8 @@ private static Object[] serverManagementCommands(BaseTransaction transaction) "Redis ver. " + REDIS_VERSION + '\n', // lolwut(1) OK, // flushall() OK, // flushall(ASYNC) + OK, // flushdb() + OK, // flushdb(ASYNC) 0L, // dbsize() }; } diff --git a/java/integTest/src/test/java/glide/cluster/CommandTests.java b/java/integTest/src/test/java/glide/cluster/CommandTests.java index 952791193c..e408142500 100644 --- a/java/integTest/src/test/java/glide/cluster/CommandTests.java +++ b/java/integTest/src/test/java/glide/cluster/CommandTests.java @@ -642,7 +642,7 @@ public void lolwut_lolwut() { @Test @SneakyThrows - public void dbsize() { + public void dbsize_and_flushdb() { assertEquals(OK, clusterClient.flushall().get()); // dbsize should be 0 after flushall() because all keys have been deleted assertEquals(0L, clusterClient.dbsize().get()); @@ -655,11 +655,27 @@ public void dbsize() { // test dbsize with routing - flush the database first to ensure the set() call is directed to a // node with 0 keys. - assertEquals(OK, clusterClient.flushall().get()); + assertEquals(OK, clusterClient.flushdb().get()); assertEquals(0L, clusterClient.dbsize().get()); + String key = UUID.randomUUID().toString(); + SingleNodeRoute route = new SlotKeyRoute(key, PRIMARY); + + // add a key, measure DB size, flush DB and measure again - with all arg combinations + assertEquals(OK, clusterClient.set(key, "foo").get()); + assertEquals(1L, clusterClient.dbsize(route).get()); + assertEquals(OK, clusterClient.flushdb(ASYNC).get()); + assertEquals(0L, clusterClient.dbsize().get()); + + assertEquals(OK, clusterClient.set(key, "foo").get()); + assertEquals(1L, clusterClient.dbsize(route).get()); + assertEquals(OK, clusterClient.flushdb(route).get()); + assertEquals(0L, clusterClient.dbsize(route).get()); + assertEquals(OK, clusterClient.set(key, "foo").get()); - assertEquals(1L, clusterClient.dbsize(new SlotKeyRoute(key, PRIMARY)).get()); + assertEquals(1L, clusterClient.dbsize(route).get()); + assertEquals(OK, clusterClient.flushdb(SYNC, route).get()); + assertEquals(0L, clusterClient.dbsize(route).get()); } @Test diff --git a/java/integTest/src/test/java/glide/standalone/CommandTests.java b/java/integTest/src/test/java/glide/standalone/CommandTests.java index a9d384b886..271970575b 100644 --- a/java/integTest/src/test/java/glide/standalone/CommandTests.java +++ b/java/integTest/src/test/java/glide/standalone/CommandTests.java @@ -343,18 +343,34 @@ public void lolwut_lolwut() { @Test @SneakyThrows - public void dbsize() { + public void dbsize_and_flushdb() { assertEquals(OK, regularClient.flushall().get()); assertEquals(OK, regularClient.select(0).get()); + // fill DB and check size int numKeys = 10; for (int i = 0; i < numKeys; i++) { assertEquals(OK, regularClient.set(UUID.randomUUID().toString(), "foo").get()); } assertEquals(10L, regularClient.dbsize().get()); + // check another empty DB assertEquals(OK, regularClient.select(1).get()); assertEquals(0L, regularClient.dbsize().get()); + + // check non-empty + assertEquals(OK, regularClient.set(UUID.randomUUID().toString(), "foo").get()); + assertEquals(1L, regularClient.dbsize().get()); + + // flush and check again + assertEquals(OK, regularClient.flushdb(SYNC).get()); + assertEquals(0L, regularClient.dbsize().get()); + + // switch to DB 0 and flush and check + assertEquals(OK, regularClient.select(0).get()); + assertEquals(10L, regularClient.dbsize().get()); + assertEquals(OK, regularClient.flushdb().get()); + assertEquals(0L, regularClient.dbsize().get()); } @Test From 0423edfd616b1ab2e005851b2b15038ace7966e0 Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Mon, 17 Jun 2024 10:10:26 -0700 Subject: [PATCH 2/4] Address PR comments. Signed-off-by: Yury-Fridlyand --- java/integTest/src/test/java/glide/cluster/CommandTests.java | 2 +- java/integTest/src/test/java/glide/standalone/CommandTests.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/integTest/src/test/java/glide/cluster/CommandTests.java b/java/integTest/src/test/java/glide/cluster/CommandTests.java index f88adf4b34..7076f24b44 100644 --- a/java/integTest/src/test/java/glide/cluster/CommandTests.java +++ b/java/integTest/src/test/java/glide/cluster/CommandTests.java @@ -664,7 +664,7 @@ public void dbsize_and_flushdb() { // add a key, measure DB size, flush DB and measure again - with all arg combinations assertEquals(OK, clusterClient.set(key, "foo").get()); assertEquals(1L, clusterClient.dbsize(route).get()); - assertEquals(OK, clusterClient.flushdb(ASYNC).get()); + assertEquals(OK, clusterClient.flushdb(SYNC).get()); assertEquals(0L, clusterClient.dbsize().get()); assertEquals(OK, clusterClient.set(key, "foo").get()); diff --git a/java/integTest/src/test/java/glide/standalone/CommandTests.java b/java/integTest/src/test/java/glide/standalone/CommandTests.java index aaa8364aad..66e62c6024 100644 --- a/java/integTest/src/test/java/glide/standalone/CommandTests.java +++ b/java/integTest/src/test/java/glide/standalone/CommandTests.java @@ -537,7 +537,7 @@ public void copy() { } } - // @Test + @Test @SneakyThrows public void functionStats_and_functionKill() { assumeTrue(REDIS_VERSION.isGreaterThanOrEqualTo("7.0.0"), "This feature added in redis 7"); From 2c345c17978733929060e505c30e93ac85a78a68 Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Mon, 17 Jun 2024 18:07:02 -0700 Subject: [PATCH 3/4] Address PR comments. Signed-off-by: Yury-Fridlyand --- .../ServerManagementClusterCommands.java | 8 ++--- .../glide/api/models/commands/FlushMode.java | 5 ++-- .../RequestRoutingConfiguration.java | 7 ++++- .../test/java/glide/cluster/CommandTests.java | 30 ++++++++++++++++--- .../java/glide/standalone/CommandTests.java | 18 +++++++++-- 5 files changed, 55 insertions(+), 13 deletions(-) diff --git a/java/client/src/main/java/glide/api/commands/ServerManagementClusterCommands.java b/java/client/src/main/java/glide/api/commands/ServerManagementClusterCommands.java index 23767d6db7..d8a7a40b88 100644 --- a/java/client/src/main/java/glide/api/commands/ServerManagementClusterCommands.java +++ b/java/client/src/main/java/glide/api/commands/ServerManagementClusterCommands.java @@ -353,7 +353,7 @@ public interface ServerManagementClusterCommands { * * @see valkey.io for details. * @param route Specifies the routing configuration for the command. The client will route the - * command to the nodes defined by route. + * command to the node defined by route. * @return OK. * @example *
    {@code
    @@ -371,7 +371,7 @@ public interface ServerManagementClusterCommands {
          * @param mode The flushing mode, could be either {@link FlushMode#SYNC} or {@link
          *     FlushMode#ASYNC}.
          * @param route Specifies the routing configuration for the command. The client will route the
    -     *     command to the nodes defined by route.
    +     *     command to the node defined by route.
          * @return OK.
          * @example
          *     
    {@code
    @@ -417,7 +417,7 @@ public interface ServerManagementClusterCommands {
          *
          * @see valkey.io for details.
          * @param route Specifies the routing configuration for the command. The client will route the
    -     *     command to the nodes defined by route.
    +     *     command to the node defined by route.
          * @return OK.
          * @example
          *     
    {@code
    @@ -435,7 +435,7 @@ public interface ServerManagementClusterCommands {
          * @param mode The flushing mode, could be either {@link FlushMode#SYNC} or {@link
          *     FlushMode#ASYNC}.
          * @param route Specifies the routing configuration for the command. The client will route the
    -     *     command to the nodes defined by route.
    +     *     command to the node defined by route.
          * @return OK.
          * @example
          *     
    {@code
    diff --git a/java/client/src/main/java/glide/api/models/commands/FlushMode.java b/java/client/src/main/java/glide/api/models/commands/FlushMode.java
    index 1594ba733a..b371abbd65 100644
    --- a/java/client/src/main/java/glide/api/models/commands/FlushMode.java
    +++ b/java/client/src/main/java/glide/api/models/commands/FlushMode.java
    @@ -22,8 +22,9 @@
      *       and {@link RedisClusterClient#functionFlush(FlushMode, Route)}.
      * 
      *
    - * @see valkey.io and valkey.io
    + * @see flushall, flushdb, and function flush at valkey.io
      */
     public enum FlushMode {
         /**
    diff --git a/java/client/src/main/java/glide/api/models/configuration/RequestRoutingConfiguration.java b/java/client/src/main/java/glide/api/models/configuration/RequestRoutingConfiguration.java
    index bea04a7e75..3e43d2dc6e 100644
    --- a/java/client/src/main/java/glide/api/models/configuration/RequestRoutingConfiguration.java
    +++ b/java/client/src/main/java/glide/api/models/configuration/RequestRoutingConfiguration.java
    @@ -31,7 +31,12 @@ public interface MultiNodeRoute extends Route {}
         @RequiredArgsConstructor
         @Getter
         public enum SimpleSingleNodeRoute implements SingleNodeRoute {
    -        /** Route request to a random node. */
    +        /**
    +         * Route request to a random node.
    + * Warning
    + * Don't use it with write commands, because they could be randomly routed to a replica (RO) + * node and fail. + */ RANDOM(2); private final int ordinal; diff --git a/java/integTest/src/test/java/glide/cluster/CommandTests.java b/java/integTest/src/test/java/glide/cluster/CommandTests.java index 7076f24b44..007820007b 100644 --- a/java/integTest/src/test/java/glide/cluster/CommandTests.java +++ b/java/integTest/src/test/java/glide/cluster/CommandTests.java @@ -43,7 +43,6 @@ import glide.api.RedisClusterClient; import glide.api.models.ClusterTransaction; import glide.api.models.ClusterValue; -import glide.api.models.commands.FlushMode; import glide.api.models.commands.InfoOptions; import glide.api.models.commands.ListDirection; import glide.api.models.commands.RangeOptions.RangeByIndex; @@ -643,6 +642,8 @@ public void lolwut_lolwut() { @Test @SneakyThrows public void dbsize_and_flushdb() { + boolean is62orHigher = REDIS_VERSION.isGreaterThanOrEqualTo("6.2.0"); + assertEquals(OK, clusterClient.flushall().get()); // dbsize should be 0 after flushall() because all keys have been deleted assertEquals(0L, clusterClient.dbsize().get()); @@ -664,7 +665,11 @@ public void dbsize_and_flushdb() { // add a key, measure DB size, flush DB and measure again - with all arg combinations assertEquals(OK, clusterClient.set(key, "foo").get()); assertEquals(1L, clusterClient.dbsize(route).get()); - assertEquals(OK, clusterClient.flushdb(SYNC).get()); + if (is62orHigher) { + assertEquals(OK, clusterClient.flushdb(SYNC).get()); + } else { + assertEquals(OK, clusterClient.flushdb(ASYNC).get()); + } assertEquals(0L, clusterClient.dbsize().get()); assertEquals(OK, clusterClient.set(key, "foo").get()); @@ -674,8 +679,18 @@ public void dbsize_and_flushdb() { assertEquals(OK, clusterClient.set(key, "foo").get()); assertEquals(1L, clusterClient.dbsize(route).get()); - assertEquals(OK, clusterClient.flushdb(SYNC, route).get()); + if (is62orHigher) { + assertEquals(OK, clusterClient.flushdb(SYNC, route).get()); + } else { + assertEquals(OK, clusterClient.flushdb(ASYNC, route).get()); + } assertEquals(0L, clusterClient.dbsize(route).get()); + + if (!is62orHigher) { + var executionException = + assertThrows(ExecutionException.class, () -> clusterClient.flushdb(SYNC).get()); + assertInstanceOf(RequestException.class, executionException.getCause()); + } } @Test @@ -812,7 +827,14 @@ public void check_does_not_throw_cross_slot_error(String testName, CompletableFu @Test @SneakyThrows public void flushall() { - assertEquals(OK, clusterClient.flushall(FlushMode.SYNC).get()); + if (REDIS_VERSION.isGreaterThanOrEqualTo("6.2.0")) { + assertEquals(OK, clusterClient.flushall(SYNC).get()); + } else { + var executionException = + assertThrows(ExecutionException.class, () -> clusterClient.flushall(SYNC).get()); + assertInstanceOf(RequestException.class, executionException.getCause()); + assertEquals(OK, clusterClient.flushall(ASYNC).get()); + } // TODO replace with KEYS command when implemented Object[] keysAfter = diff --git a/java/integTest/src/test/java/glide/standalone/CommandTests.java b/java/integTest/src/test/java/glide/standalone/CommandTests.java index 66e62c6024..7564374995 100644 --- a/java/integTest/src/test/java/glide/standalone/CommandTests.java +++ b/java/integTest/src/test/java/glide/standalone/CommandTests.java @@ -363,7 +363,14 @@ public void dbsize_and_flushdb() { assertEquals(1L, regularClient.dbsize().get()); // flush and check again - assertEquals(OK, regularClient.flushdb(SYNC).get()); + if (REDIS_VERSION.isGreaterThanOrEqualTo("6.2.0")) { + assertEquals(OK, regularClient.flushdb(SYNC).get()); + } else { + var executionException = + assertThrows(ExecutionException.class, () -> regularClient.flushdb(SYNC).get()); + assertInstanceOf(RequestException.class, executionException.getCause()); + assertEquals(OK, regularClient.flushdb(ASYNC).get()); + } assertEquals(0L, regularClient.dbsize().get()); // switch to DB 0 and flush and check @@ -392,7 +399,14 @@ public void objectFreq() { @Test @SneakyThrows public void flushall() { - assertEquals(OK, regularClient.flushall(SYNC).get()); + if (REDIS_VERSION.isGreaterThanOrEqualTo("6.2.0")) { + assertEquals(OK, regularClient.flushall(SYNC).get()); + } else { + var executionException = + assertThrows(ExecutionException.class, () -> regularClient.flushall(SYNC).get()); + assertInstanceOf(RequestException.class, executionException.getCause()); + assertEquals(OK, regularClient.flushall(ASYNC).get()); + } // TODO replace with KEYS command when implemented Object[] keysAfter = (Object[]) regularClient.customCommand(new String[] {"keys", "*"}).get(); From db1a3af8265fbab025c14ee6cc02c7fc704b4d26 Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Mon, 17 Jun 2024 18:09:09 -0700 Subject: [PATCH 4/4] Minor doc update. Signed-off-by: Yury-Fridlyand --- .../models/configuration/RequestRoutingConfiguration.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/java/client/src/main/java/glide/api/models/configuration/RequestRoutingConfiguration.java b/java/client/src/main/java/glide/api/models/configuration/RequestRoutingConfiguration.java index 3e43d2dc6e..6af6366be8 100644 --- a/java/client/src/main/java/glide/api/models/configuration/RequestRoutingConfiguration.java +++ b/java/client/src/main/java/glide/api/models/configuration/RequestRoutingConfiguration.java @@ -45,7 +45,10 @@ public enum SimpleSingleNodeRoute implements SingleNodeRoute { @RequiredArgsConstructor @Getter public enum SimpleMultiNodeRoute implements MultiNodeRoute { - /** Route request to all nodes. */ + /** + * Route request to all nodes. Warning
    + * Don't use it with write commands, they could be routed to a replica (RO) node and fail. + */ ALL_NODES(0), /** Route request to all primary nodes. */ ALL_PRIMARIES(1);