From 8d3a497d6f76b8daff3b54da525fb5559173e1d1 Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Wed, 5 Jun 2024 17:39:27 -0700 Subject: [PATCH 1/3] java: Add `FUNCTION FLUSH` command. (#288) * Add `FUNCTION FLUSH` command. Signed-off-by: Yury-Fridlyand * Minor doc update. Signed-off-by: Yury-Fridlyand * Address PR comments. Signed-off-by: Yury-Fridlyand * Apply suggestions from code review Signed-off-by: Yury-Fridlyand Co-authored-by: Andrew Carbonetto * Address PR comments. Signed-off-by: Yury-Fridlyand --------- Signed-off-by: Yury-Fridlyand Co-authored-by: Andrew Carbonetto 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 | 13 +++ .../java/glide/api/RedisClusterClient.java | 25 ++++++ .../ScriptingAndFunctionsClusterCommands.java | 67 ++++++++++++++ .../ScriptingAndFunctionsCommands.java | 31 +++++++ .../glide/api/models/BaseTransaction.java | 27 ++++++ .../glide/api/models/commands/FlushMode.java | 22 +++-- .../test/java/glide/api/RedisClientTest.java | 47 +++++++++- .../glide/api/RedisClusterClientTest.java | 89 +++++++++++++++++++ .../glide/api/models/TransactionTests.java | 5 ++ .../src/test/java/glide/TestUtilities.java | 12 +++ .../java/glide/TransactionTestUtilities.java | 9 +- .../test/java/glide/cluster/CommandTests.java | 55 +++--------- .../java/glide/standalone/CommandTests.java | 12 +-- 15 files changed, 360 insertions(+), 58 deletions(-) diff --git a/glide-core/src/protobuf/redis_request.proto b/glide-core/src/protobuf/redis_request.proto index a54b13ef41..462d315a6a 100644 --- a/glide-core/src/protobuf/redis_request.proto +++ b/glide-core/src/protobuf/redis_request.proto @@ -191,6 +191,7 @@ enum RequestType { HStrlen = 149; FunctionLoad = 150; FunctionList = 151; + FunctionFlush = 153; LMPop = 155; ExpireTime = 156; PExpireTime = 157; diff --git a/glide-core/src/request_type.rs b/glide-core/src/request_type.rs index d069336ede..be679b79e8 100644 --- a/glide-core/src/request_type.rs +++ b/glide-core/src/request_type.rs @@ -161,6 +161,7 @@ pub enum RequestType { HStrlen = 149, FunctionLoad = 150, FunctionList = 151, + FunctionFlush = 153, LMPop = 155, ExpireTime = 156, PExpireTime = 157, @@ -341,6 +342,7 @@ impl From<::protobuf::EnumOrUnknown> for RequestType { ProtobufRequestType::ZInter => RequestType::ZInter, ProtobufRequestType::FunctionLoad => RequestType::FunctionLoad, ProtobufRequestType::FunctionList => RequestType::FunctionList, + ProtobufRequestType::FunctionFlush => RequestType::FunctionFlush, ProtobufRequestType::BitPos => RequestType::BitPos, ProtobufRequestType::BitOp => RequestType::BitOp, ProtobufRequestType::HStrlen => RequestType::HStrlen, @@ -518,6 +520,7 @@ impl RequestType { RequestType::ZInter => Some(cmd("ZINTER")), RequestType::FunctionLoad => Some(get_two_word_command("FUNCTION", "LOAD")), RequestType::FunctionList => Some(get_two_word_command("FUNCTION", "LIST")), + RequestType::FunctionFlush => Some(get_two_word_command("FUNCTION", "FLUSH")), RequestType::BitPos => Some(cmd("BITPOS")), RequestType::BitOp => Some(cmd("BITOP")), RequestType::HStrlen => Some(cmd("HSTRLEN")), diff --git a/java/client/src/main/java/glide/api/RedisClient.java b/java/client/src/main/java/glide/api/RedisClient.java index 8a77bbc9e6..de3d1a10f2 100644 --- a/java/client/src/main/java/glide/api/RedisClient.java +++ b/java/client/src/main/java/glide/api/RedisClient.java @@ -16,6 +16,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.CustomCommand; import static redis_request.RedisRequestOuterClass.RequestType.Echo; import static redis_request.RedisRequestOuterClass.RequestType.FlushAll; +import static redis_request.RedisRequestOuterClass.RequestType.FunctionFlush; import static redis_request.RedisRequestOuterClass.RequestType.FunctionList; import static redis_request.RedisRequestOuterClass.RequestType.FunctionLoad; import static redis_request.RedisRequestOuterClass.RequestType.Info; @@ -225,4 +226,16 @@ public CompletableFuture[]> functionList( : new String[] {LIBRARY_NAME_REDIS_API, libNamePattern}, response -> handleFunctionListResponse(handleArrayResponse(response))); } + + @Override + public CompletableFuture functionFlush() { + return commandManager.submitNewCommand( + FunctionFlush, new String[0], this::handleStringResponse); + } + + @Override + public CompletableFuture functionFlush(@NonNull FlushMode mode) { + return commandManager.submitNewCommand( + FunctionFlush, new String[] {mode.toString()}, 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 f758ecd8eb..5f9fd1fb21 100644 --- a/java/client/src/main/java/glide/api/RedisClusterClient.java +++ b/java/client/src/main/java/glide/api/RedisClusterClient.java @@ -18,6 +18,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.CustomCommand; import static redis_request.RedisRequestOuterClass.RequestType.Echo; import static redis_request.RedisRequestOuterClass.RequestType.FlushAll; +import static redis_request.RedisRequestOuterClass.RequestType.FunctionFlush; import static redis_request.RedisRequestOuterClass.RequestType.FunctionList; import static redis_request.RedisRequestOuterClass.RequestType.FunctionLoad; import static redis_request.RedisRequestOuterClass.RequestType.Info; @@ -494,4 +495,28 @@ public CompletableFuture[]>> functionList( route, response -> handleFunctionListResponse(response, route)); } + + @Override + public CompletableFuture functionFlush() { + return commandManager.submitNewCommand( + FunctionFlush, new String[0], this::handleStringResponse); + } + + @Override + public CompletableFuture functionFlush(@NonNull FlushMode mode) { + return commandManager.submitNewCommand( + FunctionFlush, new String[] {mode.toString()}, this::handleStringResponse); + } + + @Override + public CompletableFuture functionFlush(@NonNull Route route) { + return commandManager.submitNewCommand( + FunctionFlush, new String[0], route, this::handleStringResponse); + } + + @Override + public CompletableFuture functionFlush(@NonNull FlushMode mode, @NonNull Route route) { + return commandManager.submitNewCommand( + FunctionFlush, new String[] {mode.toString()}, route, this::handleStringResponse); + } } diff --git a/java/client/src/main/java/glide/api/commands/ScriptingAndFunctionsClusterCommands.java b/java/client/src/main/java/glide/api/commands/ScriptingAndFunctionsClusterCommands.java index baa38ab057..5a1b0fd9a4 100644 --- a/java/client/src/main/java/glide/api/commands/ScriptingAndFunctionsClusterCommands.java +++ b/java/client/src/main/java/glide/api/commands/ScriptingAndFunctionsClusterCommands.java @@ -2,6 +2,7 @@ package glide.api.commands; import glide.api.models.ClusterValue; +import glide.api.models.commands.FlushMode; import glide.api.models.configuration.RequestRoutingConfiguration.Route; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -167,4 +168,70 @@ CompletableFuture[]>> functionList( */ CompletableFuture[]>> functionList( String libNamePattern, boolean withCode, Route route); + + /** + * Deletes all function libraries.
+ * The command will be routed to all primary nodes. + * + * @since Redis 7.0 and above. + * @see redis.io for details. + * @return OK. + * @example + *
{@code
+     * String response = client.functionFlush().get();
+     * assert response.equals("OK");
+     * }
+ */ + CompletableFuture functionFlush(); + + /** + * Deletes all function libraries.
+ * The command will be routed to all primary nodes. + * + * @since Redis 7.0 and above. + * @see redis.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.functionFlush(SYNC).get();
+     * assert response.equals("OK");
+     * }
+ */ + CompletableFuture functionFlush(FlushMode mode); + + /** + * Deletes all function libraries. + * + * @since Redis 7.0 and above. + * @see redis.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
+     * String response = client.functionFlush(RANDOM).get();
+     * assert response.equals("OK");
+     * }
+ */ + CompletableFuture functionFlush(Route route); + + /** + * Deletes all function libraries. + * + * @since Redis 7.0 and above. + * @see redis.io for details. + * @param route Specifies the routing configuration for the command. The client will route the + * command to the nodes defined by route. + * @param mode The flushing mode, could be either {@link FlushMode#SYNC} or {@link + * FlushMode#ASYNC}. + * @return OK. + * @example + *
{@code
+     * String response = client.functionFlush(SYNC, RANDOM).get();
+     * assert response.equals("OK");
+     * }
+ */ + CompletableFuture functionFlush(FlushMode mode, Route route); } diff --git a/java/client/src/main/java/glide/api/commands/ScriptingAndFunctionsCommands.java b/java/client/src/main/java/glide/api/commands/ScriptingAndFunctionsCommands.java index baffdf2e21..547d62a1cb 100644 --- a/java/client/src/main/java/glide/api/commands/ScriptingAndFunctionsCommands.java +++ b/java/client/src/main/java/glide/api/commands/ScriptingAndFunctionsCommands.java @@ -1,6 +1,7 @@ /** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */ package glide.api.commands; +import glide.api.models.commands.FlushMode; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -81,4 +82,34 @@ public interface ScriptingAndFunctionsCommands { * } */ CompletableFuture[]> functionList(String libNamePattern, boolean withCode); + + /** + * Deletes all function libraries. + * + * @since Redis 7.0 and above. + * @see redis.io for details. + * @return OK. + * @example + *
{@code
+     * String response = client.functionFlush().get();
+     * assert response.equals("OK");
+     * }
+ */ + CompletableFuture functionFlush(); + + /** + * Deletes all function libraries. + * + * @since Redis 7.0 and above. + * @see redis.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.functionFlush(SYNC).get();
+     * assert response.equals("OK");
+     * }
+ */ + CompletableFuture functionFlush(FlushMode mode); } 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 ea19d44700..3e4fa01892 100644 --- a/java/client/src/main/java/glide/api/models/BaseTransaction.java +++ b/java/client/src/main/java/glide/api/models/BaseTransaction.java @@ -47,6 +47,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.ExpireAt; import static redis_request.RedisRequestOuterClass.RequestType.ExpireTime; import static redis_request.RedisRequestOuterClass.RequestType.FlushAll; +import static redis_request.RedisRequestOuterClass.RequestType.FunctionFlush; import static redis_request.RedisRequestOuterClass.RequestType.FunctionList; import static redis_request.RedisRequestOuterClass.RequestType.FunctionLoad; import static redis_request.RedisRequestOuterClass.RequestType.GeoAdd; @@ -4139,6 +4140,32 @@ public T bitfieldReadOnly( return getThis(); } + /** + * Deletes all function libraries. + * + * @since Redis 7.0 and above. + * @see redis.io for details. + * @return Command Response - OK. + */ + public T functionFlush() { + protobufTransaction.addCommands(buildCommand(FunctionFlush)); + return getThis(); + } + + /** + * Deletes all function libraries. + * + * @since Redis 7.0 and above. + * @see redis.io for details. + * @param mode The flushing mode, could be either {@link FlushMode#SYNC} or {@link + * FlushMode#ASYNC}. + * @return Command Response - OK. + */ + public T functionFlush(@NonNull FlushMode mode) { + protobufTransaction.addCommands(buildCommand(FunctionFlush, buildArgs(mode.toString()))); + return getThis(); + } + /** Build protobuf {@link Command} object for given command and arguments. */ protected Command buildCommand(RequestType requestType) { return buildCommand(requestType, buildArgs()); 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 9de501f6af..69fc260ecd 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 @@ -4,17 +4,27 @@ import glide.api.RedisClient; import glide.api.RedisClusterClient; import glide.api.models.configuration.RequestRoutingConfiguration.Route; +import glide.api.models.configuration.RequestRoutingConfiguration.SingleNodeRoute; +// TODO add links to script flush /** - * Defines flushing mode for FLUSHALL command implemented by {@link - * RedisClient#flushall(FlushMode)}, {@link RedisClusterClient#flushall(FlushMode)}, and {@link - * RedisClusterClient#flushall(FlushMode, Route)}. + * Defines flushing mode for: * - * @see valkey.io + *
    + *
  • FLUSHALL command implemented by {@link RedisClient#flushall(FlushMode)}, + * {@link RedisClusterClient#flushall(FlushMode)}, and {@link + * RedisClusterClient#flushall(FlushMode, SingleNodeRoute)}. + *
  • FUNCTION FLUSH command implemented by {@link + * RedisClient#functionFlush(FlushMode)}, {@link RedisClusterClient#functionFlush(FlushMode)}, + * and {@link RedisClusterClient#functionFlush(FlushMode, Route)}. + *
+ * + * @see valkey.io and valkey.io */ public enum FlushMode { - /** Flushes the databases synchronously. */ + /** Flushes synchronously. */ SYNC, - /** Flushes the databases asynchronously. */ + /** 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 f0848e6a6e..3a5bc87e63 100644 --- a/java/client/src/test/java/glide/api/RedisClientTest.java +++ b/java/client/src/test/java/glide/api/RedisClientTest.java @@ -9,6 +9,7 @@ import static glide.api.commands.SortedSetBaseCommands.LIMIT_REDIS_API; import static glide.api.commands.SortedSetBaseCommands.WITH_SCORES_REDIS_API; import static glide.api.commands.SortedSetBaseCommands.WITH_SCORE_REDIS_API; +import static glide.api.models.commands.FlushMode.ASYNC; import static glide.api.models.commands.FlushMode.SYNC; import static glide.api.models.commands.LInsertOptions.InsertPosition.BEFORE; import static glide.api.models.commands.ScoreFilter.MAX; @@ -74,6 +75,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.ExpireAt; import static redis_request.RedisRequestOuterClass.RequestType.ExpireTime; import static redis_request.RedisRequestOuterClass.RequestType.FlushAll; +import static redis_request.RedisRequestOuterClass.RequestType.FunctionFlush; import static redis_request.RedisRequestOuterClass.RequestType.FunctionList; import static redis_request.RedisRequestOuterClass.RequestType.FunctionLoad; import static redis_request.RedisRequestOuterClass.RequestType.GeoAdd; @@ -197,6 +199,7 @@ import glide.api.models.Transaction; import glide.api.models.commands.ConditionalChange; import glide.api.models.commands.ExpireOptions; +import glide.api.models.commands.FlushMode; import glide.api.models.commands.InfoOptions; import glide.api.models.commands.ListDirection; import glide.api.models.commands.RangeOptions; @@ -4968,6 +4971,49 @@ public void functionList_with_pattern_returns_success() { assertEquals(value, payload); } + @SneakyThrows + @Test + public void functionFlush_returns_success() { + // setup + String[] args = new String[0]; + CompletableFuture testResponse = new CompletableFuture<>(); + testResponse.complete(OK); + + // match on protobuf request + when(commandManager.submitNewCommand(eq(FunctionFlush), eq(args), any())) + .thenReturn(testResponse); + + // exercise + CompletableFuture response = service.functionFlush(); + String payload = response.get(); + + // verify + assertEquals(testResponse, response); + assertEquals(OK, payload); + } + + @SneakyThrows + @Test + public void functionFlush_with_mode_returns_success() { + // setup + FlushMode mode = ASYNC; + String[] args = new String[] {mode.toString()}; + CompletableFuture testResponse = new CompletableFuture<>(); + testResponse.complete(OK); + + // match on protobuf request + when(commandManager.submitNewCommand(eq(FunctionFlush), eq(args), any())) + .thenReturn(testResponse); + + // exercise + CompletableFuture response = service.functionFlush(mode); + String payload = response.get(); + + // verify + assertEquals(testResponse, response); + assertEquals(OK, payload); + } + @SneakyThrows @Test public void bitcount_returns_success() { @@ -5377,7 +5423,6 @@ public void lset_returns_success() { long index = 0; String element = "two"; String[] arguments = new String[] {key, "0", element}; - CompletableFuture testResponse = new CompletableFuture<>(); testResponse.complete(OK); diff --git a/java/client/src/test/java/glide/api/RedisClusterClientTest.java b/java/client/src/test/java/glide/api/RedisClusterClientTest.java index 94bdb36c48..94a1ab29f3 100644 --- a/java/client/src/test/java/glide/api/RedisClusterClientTest.java +++ b/java/client/src/test/java/glide/api/RedisClusterClientTest.java @@ -3,6 +3,7 @@ import static glide.api.BaseClient.OK; import static glide.api.commands.ServerManagementCommands.VERSION_REDIS_API; +import static glide.api.models.commands.FlushMode.ASYNC; import static glide.api.models.commands.FlushMode.SYNC; import static glide.api.models.commands.function.FunctionListOptions.LIBRARY_NAME_REDIS_API; import static glide.api.models.commands.function.FunctionListOptions.WITH_CODE_REDIS_API; @@ -25,6 +26,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.ConfigSet; import static redis_request.RedisRequestOuterClass.RequestType.Echo; import static redis_request.RedisRequestOuterClass.RequestType.FlushAll; +import static redis_request.RedisRequestOuterClass.RequestType.FunctionFlush; import static redis_request.RedisRequestOuterClass.RequestType.FunctionList; import static redis_request.RedisRequestOuterClass.RequestType.FunctionLoad; import static redis_request.RedisRequestOuterClass.RequestType.Info; @@ -35,6 +37,7 @@ 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.function.FunctionLoadOptions; import glide.api.models.configuration.RequestRoutingConfiguration.Route; @@ -1272,4 +1275,90 @@ public void functionList_with_pattern_and_route_returns_success() { assertEquals(testResponse, response); assertEquals(value, payload.getSingleValue()); } + + @SneakyThrows + @Test + public void functionFlush_returns_success() { + // setup + String[] args = new String[0]; + CompletableFuture testResponse = new CompletableFuture<>(); + testResponse.complete(OK); + + // match on protobuf request + when(commandManager.submitNewCommand(eq(FunctionFlush), eq(args), any())) + .thenReturn(testResponse); + + // exercise + CompletableFuture response = service.functionFlush(); + String payload = response.get(); + + // verify + assertEquals(testResponse, response); + assertEquals(OK, payload); + } + + @SneakyThrows + @Test + public void functionFlush_with_mode_returns_success() { + // setup + FlushMode mode = ASYNC; + String[] args = new String[] {mode.toString()}; + CompletableFuture testResponse = new CompletableFuture<>(); + testResponse.complete(OK); + + // match on protobuf request + when(commandManager.submitNewCommand(eq(FunctionFlush), eq(args), any())) + .thenReturn(testResponse); + + // exercise + CompletableFuture response = service.functionFlush(mode); + String payload = response.get(); + + // verify + assertEquals(testResponse, response); + assertEquals(OK, payload); + } + + @SneakyThrows + @Test + public void functionFlush_with_route_returns_success() { + // setup + String[] args = new String[0]; + CompletableFuture testResponse = new CompletableFuture<>(); + testResponse.complete(OK); + + // match on protobuf request + when(commandManager.submitNewCommand(eq(FunctionFlush), eq(args), eq(RANDOM), any())) + .thenReturn(testResponse); + + // exercise + CompletableFuture response = service.functionFlush(RANDOM); + String payload = response.get(); + + // verify + assertEquals(testResponse, response); + assertEquals(OK, payload); + } + + @SneakyThrows + @Test + public void functionFlush_with_mode_and_route_returns_success() { + // setup + FlushMode mode = ASYNC; + String[] args = new String[] {mode.toString()}; + CompletableFuture testResponse = new CompletableFuture<>(); + testResponse.complete(OK); + + // match on protobuf request + when(commandManager.submitNewCommand(eq(FunctionFlush), eq(args), eq(RANDOM), any())) + .thenReturn(testResponse); + + // exercise + CompletableFuture response = service.functionFlush(mode, RANDOM); + String payload = response.get(); + + // verify + assertEquals(testResponse, response); + assertEquals(OK, payload); + } } 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 11a23ee584..02fe79fc26 100644 --- a/java/client/src/test/java/glide/api/models/TransactionTests.java +++ b/java/client/src/test/java/glide/api/models/TransactionTests.java @@ -57,6 +57,7 @@ import static redis_request.RedisRequestOuterClass.RequestType.ExpireAt; import static redis_request.RedisRequestOuterClass.RequestType.ExpireTime; import static redis_request.RedisRequestOuterClass.RequestType.FlushAll; +import static redis_request.RedisRequestOuterClass.RequestType.FunctionFlush; import static redis_request.RedisRequestOuterClass.RequestType.FunctionList; import static redis_request.RedisRequestOuterClass.RequestType.FunctionLoad; import static redis_request.RedisRequestOuterClass.RequestType.GeoAdd; @@ -942,6 +943,10 @@ InfScoreBound.NEGATIVE_INFINITY, new ScoreBoundary(3, false), new Limit(1, 2)), transaction.sintercard(new String[] {"key1", "key2"}, 1); results.add(Pair.of(SInterCard, buildArgs("2", "key1", "key2", "LIMIT", "1"))); + transaction.functionFlush().functionFlush(ASYNC); + results.add(Pair.of(FunctionFlush, buildArgs())); + results.add(Pair.of(FunctionFlush, buildArgs("ASYNC"))); + var protobufTransaction = transaction.getProtobufTransaction().build(); for (int idx = 0; idx < protobufTransaction.getCommandsCount(); idx++) { diff --git a/java/integTest/src/test/java/glide/TestUtilities.java b/java/integTest/src/test/java/glide/TestUtilities.java index 3b77497fcd..9337595389 100644 --- a/java/integTest/src/test/java/glide/TestUtilities.java +++ b/java/integTest/src/test/java/glide/TestUtilities.java @@ -163,4 +163,16 @@ public static void checkFunctionListResponse( } assertTrue(hasLib); } + + /** Generate a dummy LUA library code. */ + public static String generateLuaLibCode(String libName, List funcNames) { + StringBuilder code = new StringBuilder("#!lua name=" + libName + "\n"); + for (var funcName : funcNames) { + code.append("redis.register_function('") + .append(funcName) + // function returns first argument + .append("', function(keys, args) return args[1] end)\n"); + } + return code.toString(); + } } diff --git a/java/integTest/src/test/java/glide/TransactionTestUtilities.java b/java/integTest/src/test/java/glide/TransactionTestUtilities.java index 08abd14ae6..c99b5b228d 100644 --- a/java/integTest/src/test/java/glide/TransactionTestUtilities.java +++ b/java/integTest/src/test/java/glide/TransactionTestUtilities.java @@ -4,6 +4,7 @@ import static glide.TestConfiguration.REDIS_VERSION; import static glide.api.BaseClient.OK; import static glide.api.models.commands.FlushMode.ASYNC; +import static glide.api.models.commands.FlushMode.SYNC; import static glide.api.models.commands.LInsertOptions.InsertPosition.AFTER; import static glide.api.models.commands.ScoreFilter.MAX; import static glide.api.models.commands.ScoreFilter.MIN; @@ -702,24 +703,24 @@ private static Object[] scriptingAndFunctionsCommands(BaseTransaction transac }; transaction - .customCommand(new String[] {"function", "flush", "sync"}) + .functionFlush(SYNC) .functionList(false) .functionList(true) .functionLoad(code, false) .functionLoad(code, true) .functionList("otherLib", false) .functionList("mylib1T", true) - .customCommand(new String[] {"function", "flush", "sync"}); + .functionFlush(); return new Object[] { - OK, // customCommand("function", "flush", "sync") + OK, // functionFlush(SYNC) new Map[0], // functionList(false) new Map[0], // functionList(true) "mylib1T", // functionLoad(code, false) "mylib1T", // functionLoad(code, true) new Map[0], // functionList("otherLib", false) expectedLibData, // functionList("mylib1T", true) - OK, // customCommand("function", "flush", "sync") + OK, // functionFlush() }; } diff --git a/java/integTest/src/test/java/glide/cluster/CommandTests.java b/java/integTest/src/test/java/glide/cluster/CommandTests.java index 4d2779b8bc..da0ad10cd9 100644 --- a/java/integTest/src/test/java/glide/cluster/CommandTests.java +++ b/java/integTest/src/test/java/glide/cluster/CommandTests.java @@ -4,10 +4,13 @@ import static glide.TestConfiguration.CLUSTER_PORTS; import static glide.TestConfiguration.REDIS_VERSION; import static glide.TestUtilities.checkFunctionListResponse; +import static glide.TestUtilities.generateLuaLibCode; import static glide.TestUtilities.getFirstEntryFromMultiValue; import static glide.TestUtilities.getValueFromInfo; import static glide.TestUtilities.parseInfoResponseToMap; import static glide.api.BaseClient.OK; +import static glide.api.models.commands.FlushMode.ASYNC; +import static glide.api.models.commands.FlushMode.SYNC; import static glide.api.models.commands.InfoOptions.Section.CLIENTS; import static glide.api.models.commands.InfoOptions.Section.CLUSTER; import static glide.api.models.commands.InfoOptions.Section.COMMANDSTATS; @@ -767,8 +770,8 @@ public void flushall() { var route = new SlotKeyRoute("key", PRIMARY); assertEquals(OK, clusterClient.flushall().get()); assertEquals(OK, clusterClient.flushall(route).get()); - assertEquals(OK, clusterClient.flushall(FlushMode.ASYNC).get()); - assertEquals(OK, clusterClient.flushall(FlushMode.ASYNC, route).get()); + assertEquals(OK, clusterClient.flushall(ASYNC).get()); + assertEquals(OK, clusterClient.flushall(ASYNC, route).get()); var replicaRoute = new SlotKeyRoute("key", REPLICA); // command should fail on a replica, because it is read-only @@ -788,24 +791,13 @@ public void flushall() { public void functionLoad_and_functionList(boolean singleNodeRoute) { assumeTrue(REDIS_VERSION.isGreaterThanOrEqualTo("7.0.0"), "This feature added in redis 7"); - // TODO use FUNCTION FLUSH - assertEquals( - OK, - clusterClient - .customCommand(new String[] {"FUNCTION", "FLUSH", "SYNC"}) - .get() - .getSingleValue()); - String libName = "mylib1c_" + singleNodeRoute; String funcName = "myfunc1c_" + singleNodeRoute; - String code = - "#!lua name=" - + libName - + " \n redis.register_function('" - + funcName - + "', function(keys, args) return args[1] end)"; // function returns first argument + + String code = generateLuaLibCode(libName, List.of(funcName)); Route route = singleNodeRoute ? new SlotKeyRoute("1", PRIMARY) : ALL_PRIMARIES; + assertEquals(OK, clusterClient.functionFlush(SYNC, route).get()); assertEquals(libName, clusterClient.functionLoad(code, false, route).get()); // TODO test function with FCALL when fixed in redis-rs and implemented @@ -857,11 +849,7 @@ public void functionLoad_and_functionList(boolean singleNodeRoute) { // re-load library with overwriting assertEquals(libName, clusterClient.functionLoad(code, true, route).get()); String newFuncName = "myfunc2c_" + singleNodeRoute; - String newCode = - code - + "\n redis.register_function('" - + newFuncName - + "', function(keys, args) return #args end)"; // function returns argument count + String newCode = generateLuaLibCode(libName, List.of(funcName, newFuncName)); assertEquals(libName, clusterClient.functionLoad(newCode, true, route).get()); @@ -894,7 +882,7 @@ public void functionLoad_and_functionList(boolean singleNodeRoute) { // TODO test with FCALL - // TODO FUNCTION FLUSH at the end + assertEquals(OK, clusterClient.functionFlush(route).get()); } @SneakyThrows @@ -902,22 +890,11 @@ public void functionLoad_and_functionList(boolean singleNodeRoute) { public void functionLoad_and_functionList_without_route() { assumeTrue(REDIS_VERSION.isGreaterThanOrEqualTo("7.0.0"), "This feature added in redis 7"); - // TODO use FUNCTION FLUSH - assertEquals( - OK, - clusterClient - .customCommand(new String[] {"FUNCTION", "FLUSH", "SYNC"}) - .get() - .getSingleValue()); + assertEquals(OK, clusterClient.functionFlush(SYNC).get()); String libName = "mylib1c"; String funcName = "myfunc1c"; - String code = - "#!lua name=" - + libName - + " \n redis.register_function('" - + funcName - + "', function(keys, args) return args[1] end)"; // function returns first argument + String code = generateLuaLibCode(libName, List.of(funcName)); assertEquals(libName, clusterClient.functionLoad(code, false).get()); // TODO test function with FCALL when fixed in redis-rs and implemented @@ -951,11 +928,7 @@ public void functionLoad_and_functionList_without_route() { // re-load library with overwriting assertEquals(libName, clusterClient.functionLoad(code, true).get()); String newFuncName = "myfunc2c"; - String newCode = - code - + "\n redis.register_function('" - + newFuncName - + "', function(keys, args) return #args end)"; // function returns argument count + String newCode = generateLuaLibCode(libName, List.of(funcName, newFuncName)); assertEquals(libName, clusterClient.functionLoad(newCode, true).get()); flist = clusterClient.functionList(libName, false).get(); @@ -969,6 +942,6 @@ public void functionLoad_and_functionList_without_route() { // TODO test with FCALL - // TODO FUNCTION FLUSH at the end + assertEquals(OK, clusterClient.functionFlush(ASYNC).get()); } } diff --git a/java/integTest/src/test/java/glide/standalone/CommandTests.java b/java/integTest/src/test/java/glide/standalone/CommandTests.java index adafed5406..8a9c592e21 100644 --- a/java/integTest/src/test/java/glide/standalone/CommandTests.java +++ b/java/integTest/src/test/java/glide/standalone/CommandTests.java @@ -7,6 +7,8 @@ import static glide.TestUtilities.getValueFromInfo; import static glide.TestUtilities.parseInfoResponseToMap; import static glide.api.BaseClient.OK; +import static glide.api.models.commands.FlushMode.ASYNC; +import static glide.api.models.commands.FlushMode.SYNC; import static glide.api.models.commands.InfoOptions.Section.CLUSTER; import static glide.api.models.commands.InfoOptions.Section.CPU; import static glide.api.models.commands.InfoOptions.Section.EVERYTHING; @@ -24,7 +26,6 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue; import glide.api.RedisClient; -import glide.api.models.commands.FlushMode; import glide.api.models.commands.InfoOptions; import glide.api.models.configuration.NodeAddress; import glide.api.models.configuration.RedisClientConfiguration; @@ -361,14 +362,14 @@ public void objectFreq() { @Test @SneakyThrows public void flushall() { - assertEquals(OK, regularClient.flushall(FlushMode.SYNC).get()); + assertEquals(OK, regularClient.flushall(SYNC).get()); // TODO replace with KEYS command when implemented Object[] keysAfter = (Object[]) regularClient.customCommand(new String[] {"keys", "*"}).get(); assertEquals(0, keysAfter.length); assertEquals(OK, regularClient.flushall().get()); - assertEquals(OK, regularClient.flushall(FlushMode.ASYNC).get()); + assertEquals(OK, regularClient.flushall(ASYNC).get()); } @SneakyThrows @@ -376,8 +377,7 @@ public void flushall() { public void functionLoad_and_functionList() { assumeTrue(REDIS_VERSION.isGreaterThanOrEqualTo("7.0.0"), "This feature added in redis 7"); - // TODO use FUNCTION FLUSH - assertEquals(OK, regularClient.customCommand(new String[] {"FUNCTION", "FLUSH", "SYNC"}).get()); + assertEquals(OK, regularClient.functionFlush(SYNC).get()); String libName = "mylib1c"; String funcName = "myfunc1c"; @@ -436,6 +436,6 @@ public void functionLoad_and_functionList() { flist, libName, expectedDescription, expectedFlags, Optional.of(newCode)); // TODO test with FCALL - // TODO FUNCTION FLUSH at the end + assertEquals(OK, regularClient.functionFlush(ASYNC).get()); } } From 431de97bea94893fcfb2bb0263194c42e77d1618 Mon Sep 17 00:00:00 2001 From: Yury-Fridlyand Date: Thu, 6 Jun 2024 10:34:33 -0700 Subject: [PATCH 2/3] Address PR comments. Signed-off-by: Yury-Fridlyand --- .../api/commands/ScriptingAndFunctionsClusterCommands.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/client/src/main/java/glide/api/commands/ScriptingAndFunctionsClusterCommands.java b/java/client/src/main/java/glide/api/commands/ScriptingAndFunctionsClusterCommands.java index 5a1b0fd9a4..5a10354185 100644 --- a/java/client/src/main/java/glide/api/commands/ScriptingAndFunctionsClusterCommands.java +++ b/java/client/src/main/java/glide/api/commands/ScriptingAndFunctionsClusterCommands.java @@ -222,10 +222,10 @@ CompletableFuture[]>> functionList( * * @since Redis 7.0 and above. * @see redis.io for details. - * @param route Specifies the routing configuration for the command. The client will route the - * command to the nodes defined by route. * @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

From 968327eb9301c761bb105efe04a6952716d30731 Mon Sep 17 00:00:00 2001
From: Yury-Fridlyand 
Date: Fri, 7 Jun 2024 11:44:55 -0700
Subject: [PATCH 3/3] Address PR comments.

Signed-off-by: Yury-Fridlyand 
---
 java/client/src/test/java/glide/api/RedisClientTest.java | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/java/client/src/test/java/glide/api/RedisClientTest.java b/java/client/src/test/java/glide/api/RedisClientTest.java
index 323d00c4f7..630f66bf17 100644
--- a/java/client/src/test/java/glide/api/RedisClientTest.java
+++ b/java/client/src/test/java/glide/api/RedisClientTest.java
@@ -5021,9 +5021,8 @@ public void functionDelete_returns_success() {
         // setup
         String libName = "GLIDE";
         String[] args = new String[] {libName};
-        String value = OK;
         CompletableFuture testResponse = new CompletableFuture<>();
-        testResponse.complete(value);
+        testResponse.complete(OK);
 
         // match on protobuf request
         when(commandManager.submitNewCommand(eq(FunctionDelete), eq(args), any()))