diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index a065c2321..5a7372b64 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -8,10 +8,12 @@ on: branches: - main - '[0-9].*' + - 'feature/*' pull_request: branches: - main - '[0-9].*' + - 'feature/*' schedule: - cron: '0 1 * * *' # nightly build workflow_dispatch: diff --git a/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java b/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java index 1a8994d28..1d87e2c13 100644 --- a/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java +++ b/src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java @@ -1489,6 +1489,11 @@ public RedisFuture ftCreate(K index, CreateArgs options, List ftDropindex(K index, boolean deleteDocumentKeys) { + return dispatch(searchCommandBuilder.ftDropindex(index, deleteDocumentKeys)); + } + @Override public RedisFuture> jsonArrappend(K key, JsonPath jsonPath, JsonValue... values) { return dispatch(jsonCommandBuilder.jsonArrappend(key, jsonPath, values)); diff --git a/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java b/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java index 02f37afd4..186ec8b14 100644 --- a/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java +++ b/src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java @@ -1553,6 +1553,11 @@ public Mono ftCreate(K index, CreateArgs options, List> f return createMono(() -> searchCommandBuilder.ftCreate(index, options, fields)); } + @Override + public Mono ftDropindex(K index, boolean deleteDocumentKeys) { + return createMono(() -> searchCommandBuilder.ftDropindex(index, deleteDocumentKeys)); + } + @Override public Flux jsonArrappend(K key, JsonPath jsonPath, JsonValue... values) { return createDissolvingFlux(() -> jsonCommandBuilder.jsonArrappend(key, jsonPath, values)); diff --git a/src/main/java/io/lettuce/core/RediSearchCommandBuilder.java b/src/main/java/io/lettuce/core/RediSearchCommandBuilder.java index 1f8f25d30..6ed8acac6 100644 --- a/src/main/java/io/lettuce/core/RediSearchCommandBuilder.java +++ b/src/main/java/io/lettuce/core/RediSearchCommandBuilder.java @@ -12,6 +12,7 @@ import io.lettuce.core.protocol.Command; import io.lettuce.core.protocol.CommandArgs; import io.lettuce.core.protocol.CommandKeyword; +import io.lettuce.core.protocol.RedisCommand; import io.lettuce.core.search.arguments.CreateArgs; import io.lettuce.core.search.Field; @@ -60,4 +61,16 @@ public Command ftCreate(K index, CreateArgs createArgs, List } + public Command ftDropindex(K index, boolean deleteDocumentKeys) { + notNullKey(index); + + CommandArgs args = new CommandArgs<>(codec).addKey(index); + + if (deleteDocumentKeys) { + args.add(CommandKeyword.DD); + } + + return createCommand(FT_DROPINDEX, new StatusOutput<>(codec), args); + } + } diff --git a/src/main/java/io/lettuce/core/api/async/RediSearchAsyncCommands.java b/src/main/java/io/lettuce/core/api/async/RediSearchAsyncCommands.java index 7b549160c..dd52f9aff 100644 --- a/src/main/java/io/lettuce/core/api/async/RediSearchAsyncCommands.java +++ b/src/main/java/io/lettuce/core/api/async/RediSearchAsyncCommands.java @@ -35,4 +35,21 @@ public interface RediSearchAsyncCommands { */ RedisFuture ftCreate(K index, CreateArgs options, List> fields); + /** + * Drop an index. + *

+ * By default, FT.DROPINDEX does not delete the documents + * associated with the index. Adding the deleteDocuments option deletes the documents as well. If an index + * creation is still running (FT.CREATE is running + * asynchronously), only the document hashes that have already been indexed are deleted. The document hashes left to be + * indexed remain in the database. + * + * @param index the index name, as a key + * @param deleteDocuments if true, delete the documents as well + * @return the result of the drop command + * @since 6.6 + * @see FT.DROPINDEX + */ + RedisFuture ftDropindex(K index, boolean deleteDocuments); + } diff --git a/src/main/java/io/lettuce/core/api/reactive/RediSearchReactiveCommands.java b/src/main/java/io/lettuce/core/api/reactive/RediSearchReactiveCommands.java index ba2268cca..631d1543b 100644 --- a/src/main/java/io/lettuce/core/api/reactive/RediSearchReactiveCommands.java +++ b/src/main/java/io/lettuce/core/api/reactive/RediSearchReactiveCommands.java @@ -35,4 +35,21 @@ public interface RediSearchReactiveCommands { */ Mono ftCreate(K index, CreateArgs options, List> fields); + /** + * Drop an index. + *

+ * By default, FT.DROPINDEX does not delete the documents + * associated with the index. Adding the deleteDocuments option deletes the documents as well. If an index + * creation is still running (FT.CREATE is running + * asynchronously), only the document hashes that have already been indexed are deleted. The document hashes left to be + * indexed remain in the database. + * + * @param index the index name, as a key + * @param deleteDocuments if true, delete the documents as well + * @return the result of the drop command + * @since 6.6 + * @see FT.DROPINDEX + */ + Mono ftDropindex(K index, boolean deleteDocuments); + } diff --git a/src/main/java/io/lettuce/core/api/sync/RediSearchCommands.java b/src/main/java/io/lettuce/core/api/sync/RediSearchCommands.java index c76f9867e..24814b8c5 100644 --- a/src/main/java/io/lettuce/core/api/sync/RediSearchCommands.java +++ b/src/main/java/io/lettuce/core/api/sync/RediSearchCommands.java @@ -34,4 +34,21 @@ public interface RediSearchCommands { */ String ftCreate(K index, CreateArgs options, List> fields); + /** + * Drop an index. + *

+ * By default, FT.DROPINDEX does not delete the documents + * associated with the index. Adding the deleteDocuments option deletes the documents as well. If an index + * creation is still running (FT.CREATE is running + * asynchronously), only the document hashes that have already been indexed are deleted. The document hashes left to be + * indexed remain in the database. + * + * @param index the index name, as a key + * @param deleteDocuments if true, delete the documents as well + * @return the result of the drop command + * @since 6.6 + * @see FT.DROPINDEX + */ + String ftDropindex(K index, boolean deleteDocuments); + } diff --git a/src/main/java/io/lettuce/core/cluster/api/async/RediSearchAsyncCommands.java b/src/main/java/io/lettuce/core/cluster/api/async/RediSearchAsyncCommands.java index d9fb18925..11f4cf307 100644 --- a/src/main/java/io/lettuce/core/cluster/api/async/RediSearchAsyncCommands.java +++ b/src/main/java/io/lettuce/core/cluster/api/async/RediSearchAsyncCommands.java @@ -34,4 +34,21 @@ public interface RediSearchAsyncCommands { */ AsyncExecutions ftCreate(K index, CreateArgs options, List> fields); + /** + * Drop an index. + *

+ * By default, FT.DROPINDEX does not delete the documents + * associated with the index. Adding the deleteDocuments option deletes the documents as well. If an index + * creation is still running (FT.CREATE is running + * asynchronously), only the document hashes that have already been indexed are deleted. The document hashes left to be + * indexed remain in the database. + * + * @param index the index name, as a key + * @param deleteDocuments if true, delete the documents as well + * @return the result of the drop command + * @since 6.6 + * @see FT.DROPINDEX + */ + AsyncExecutions ftDropindex(K index, boolean deleteDocuments); + } diff --git a/src/main/java/io/lettuce/core/cluster/api/sync/RediSearchCommands.java b/src/main/java/io/lettuce/core/cluster/api/sync/RediSearchCommands.java index 00cbc7b8b..43fa159be 100644 --- a/src/main/java/io/lettuce/core/cluster/api/sync/RediSearchCommands.java +++ b/src/main/java/io/lettuce/core/cluster/api/sync/RediSearchCommands.java @@ -34,4 +34,21 @@ public interface RediSearchCommands { */ Executions ftCreate(K index, CreateArgs options, List> fields); + /** + * Drop an index. + *

+ * By default, FT.DROPINDEX does not delete the documents + * associated with the index. Adding the deleteDocuments option deletes the documents as well. If an index + * creation is still running (FT.CREATE is running + * asynchronously), only the document hashes that have already been indexed are deleted. The document hashes left to be + * indexed remain in the database. + * + * @param index the index name, as a key + * @param deleteDocuments if true, delete the documents as well + * @return the result of the drop command + * @since 6.6 + * @see FT.DROPINDEX + */ + Executions ftDropindex(K index, boolean deleteDocuments); + } diff --git a/src/main/java/io/lettuce/core/protocol/CommandKeyword.java b/src/main/java/io/lettuce/core/protocol/CommandKeyword.java index 62c6e84cd..dce6684aa 100644 --- a/src/main/java/io/lettuce/core/protocol/CommandKeyword.java +++ b/src/main/java/io/lettuce/core/protocol/CommandKeyword.java @@ -53,7 +53,7 @@ public enum CommandKeyword implements ProtocolKeyword { MAXTEXTFIELDS, PREFIX, FILTER, LANGUAGE, LANGUAGE_FIELD, SCORE, SCORE_FIELD, PAYLOAD_FIELD, TEMPORARY, NOOFFSETS, NOHL, NOFIELDS, NOFREQS, SKIPINITIALSCAN, STOPWORDS, AS, SORTABLE, SCHEMA, UNF, NOINDEX, - NOSTEM, PHONETIC, WEIGHT, SEPARATOR, CASESENSITIVE, WITHSUFFIXTRIE, INDEXEMPTY, INDEXMISSING; + NOSTEM, PHONETIC, WEIGHT, SEPARATOR, CASESENSITIVE, WITHSUFFIXTRIE, INDEXEMPTY, INDEXMISSING, DD; public final byte[] bytes; diff --git a/src/main/java/io/lettuce/core/protocol/CommandType.java b/src/main/java/io/lettuce/core/protocol/CommandType.java index 3d5b9f4e9..f615ae4af 100644 --- a/src/main/java/io/lettuce/core/protocol/CommandType.java +++ b/src/main/java/io/lettuce/core/protocol/CommandType.java @@ -113,7 +113,7 @@ public enum CommandType implements ProtocolKeyword { "JSON.STRLEN"), JSON_TOGGLE("JSON.TOGGLE"), JSON_TYPE("JSON.TYPE"), // RediSearch - FT_CREATE("FT.CREATE"), + FT_CREATE("FT.CREATE"), FT_DROPINDEX("FT.DROPINDEX"), // Others diff --git a/src/main/kotlin/io/lettuce/core/api/coroutines/RediSearchCoroutinesCommands.kt b/src/main/kotlin/io/lettuce/core/api/coroutines/RediSearchCoroutinesCommands.kt index f6a24da5a..22bb118d5 100644 --- a/src/main/kotlin/io/lettuce/core/api/coroutines/RediSearchCoroutinesCommands.kt +++ b/src/main/kotlin/io/lettuce/core/api/coroutines/RediSearchCoroutinesCommands.kt @@ -37,5 +37,22 @@ interface RediSearchCoroutinesCommands { */ suspend fun ftCreate(index: K, options: CreateArgs, fields: List>): String? + /** + * Drop an index. + *

+ * By default, FT.DROPINDEX does not delete the documents + * associated with the index. Adding the deleteDocuments option deletes the documents as well. If an index + * creation is still running (FT.CREATE is running + * asynchronously), only the document hashes that have already been indexed are deleted. The document hashes left to be + * indexed remain in the database. + * + * @param index the index name, as a key + * @param deleteDocuments if true, delete the documents as well + * @return the result of the drop command + * @since 6.6 + * @see FT.DROPINDEX + */ + suspend fun ftDropindex(index: K, deleteDocuments: Boolean): String? + } diff --git a/src/main/templates/io/lettuce/core/api/RediSearchCommands.java b/src/main/templates/io/lettuce/core/api/RediSearchCommands.java index 9c348db9c..d2c0455a7 100644 --- a/src/main/templates/io/lettuce/core/api/RediSearchCommands.java +++ b/src/main/templates/io/lettuce/core/api/RediSearchCommands.java @@ -34,4 +34,21 @@ public interface RediSearchCommands { */ String ftCreate(K index, CreateArgs options, List> fields); + /** + * Drop an index. + *

+ * By default, FT.DROPINDEX does not delete the documents + * associated with the index. Adding the deleteDocuments option deletes the documents as well. If an index + * creation is still running (FT.CREATE is running + * asynchronously), only the document hashes that have already been indexed are deleted. The document hashes left to be + * indexed remain in the database. + * + * @param index the index name, as a key + * @param deleteDocuments if true, delete the documents as well + * @return the result of the drop command + * @since 6.6 + * @see FT.DROPINDEX + */ + String ftDropindex(K index, boolean deleteDocuments); + } diff --git a/src/test/java/io/lettuce/core/RediSearchCommandBuilderUnitTests.java b/src/test/java/io/lettuce/core/RediSearchCommandBuilderUnitTests.java index c84e232eb..05edd0b55 100644 --- a/src/test/java/io/lettuce/core/RediSearchCommandBuilderUnitTests.java +++ b/src/test/java/io/lettuce/core/RediSearchCommandBuilderUnitTests.java @@ -89,4 +89,26 @@ void shouldCorrectlyConstructFtCreateCommandScenario2() { assertThat(buf.toString(StandardCharsets.UTF_8)).isEqualTo(result); } + @Test + void shouldCorrectlyConstructFtDropindexCommand() { + Command command = builder.ftDropindex(MY_KEY, false); + ByteBuf buf = Unpooled.directBuffer(); + command.encode(buf); + + String result = "*2\r\n" + "$12\r\n" + "FT.DROPINDEX\r\n" + "$3\r\n" + MY_KEY + "\r\n"; + + assertThat(buf.toString(StandardCharsets.UTF_8)).isEqualTo(result); + } + + @Test + void shouldCorrectlyConstructFtDropindexCommandDd() { + Command command = builder.ftDropindex(MY_KEY, true); + ByteBuf buf = Unpooled.directBuffer(); + command.encode(buf); + + String result = "*3\r\n" + "$12\r\n" + "FT.DROPINDEX\r\n" + "$3\r\n" + MY_KEY + "\r\n" + "$2\r\n" + "DD\r\n"; + + assertThat(buf.toString(StandardCharsets.UTF_8)).isEqualTo(result); + } + } diff --git a/src/test/java/io/lettuce/core/cluster/AsyncConnectionProviderIntegrationTests.java b/src/test/java/io/lettuce/core/cluster/AsyncConnectionProviderIntegrationTests.java index 712d5af9e..966d0a052 100644 --- a/src/test/java/io/lettuce/core/cluster/AsyncConnectionProviderIntegrationTests.java +++ b/src/test/java/io/lettuce/core/cluster/AsyncConnectionProviderIntegrationTests.java @@ -23,6 +23,7 @@ import static org.assertj.core.api.Assertions.*; import java.io.IOException; +import java.net.ConnectException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; @@ -151,12 +152,12 @@ void connectShouldFail() throws Exception { StopWatch stopWatch = new StopWatch(); assertThatThrownBy(() -> TestFutures.awaitOrTimeout(sut.getConnection(connectionKey))) - .hasCauseInstanceOf(ConnectTimeoutException.class); + .hasRootCauseInstanceOf(ConnectException.class); stopWatch.start(); assertThatThrownBy(() -> TestFutures.awaitOrTimeout(sut.getConnection(connectionKey))) - .hasCauseInstanceOf(ConnectTimeoutException.class); + .hasRootCauseInstanceOf(ConnectException.class); stopWatch.stop(); diff --git a/src/test/java/io/lettuce/core/json/RediSearchIntegrationTests.java b/src/test/java/io/lettuce/core/json/RediSearchIntegrationTests.java index c87472bc6..ca70d2129 100644 --- a/src/test/java/io/lettuce/core/json/RediSearchIntegrationTests.java +++ b/src/test/java/io/lettuce/core/json/RediSearchIntegrationTests.java @@ -8,6 +8,7 @@ package io.lettuce.core.json; import io.lettuce.core.RedisClient; +import io.lettuce.core.RedisCommandExecutionException; import io.lettuce.core.RedisContainerIntegrationTests; import io.lettuce.core.RedisURI; import io.lettuce.core.api.sync.RedisCommands; @@ -26,6 +27,7 @@ import static io.lettuce.TestTags.INTEGRATION_TEST; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; @Tag(INTEGRATION_TEST) public class RediSearchIntegrationTests extends RedisContainerIntegrationTests { @@ -79,6 +81,9 @@ void ftCreateScenario1() { String result = redis.ftCreate(GENERIC_INDEX, createArgs, Arrays.asList(field1, field2, field3)); assertThat(result).isEqualTo("OK"); + + result = redis.ftDropindex(GENERIC_INDEX, false); + assertThat(result).isEqualTo("OK"); } } diff --git a/src/test/resources/docker/docker-compose.yml b/src/test/resources/docker/docker-compose.yml index 2cc05fa3d..58a83da33 100644 --- a/src/test/resources/docker/docker-compose.yml +++ b/src/test/resources/docker/docker-compose.yml @@ -1,6 +1,6 @@ --- x-client-libs-stack-image: &client-libs-stack-image - image: "redislabs/client-libs-test:${REDIS_STACK_VERSION:-8.0-M02}" + image: "redislabs/client-libs-test:${REDIS_STACK_VERSION:-8.0-M04-pre}" services: