From 60a273f6dc4c484ce5dd2c25a6b2923ee4823174 Mon Sep 17 00:00:00 2001 From: "TURKCELL\\TCASENOCAK" Date: Wed, 8 Oct 2025 11:27:38 +0300 Subject: [PATCH 1/2] feat: add CommandListener interface for monitoring Redis command operations --- .../redis/om/spring/ops/CommandListener.java | 90 +++++++ .../om/spring/ops/RedisModulesOperations.java | 8 +- .../ops/search/SearchOperationsImpl.java | 229 ++++++++++++------ 3 files changed, 251 insertions(+), 76 deletions(-) create mode 100644 redis-om-spring/src/main/java/com/redis/om/spring/ops/CommandListener.java diff --git a/redis-om-spring/src/main/java/com/redis/om/spring/ops/CommandListener.java b/redis-om-spring/src/main/java/com/redis/om/spring/ops/CommandListener.java new file mode 100644 index 00000000..ecc96fcc --- /dev/null +++ b/redis-om-spring/src/main/java/com/redis/om/spring/ops/CommandListener.java @@ -0,0 +1,90 @@ +package com.redis.om.spring.ops; + +import com.redis.om.spring.autocomplete.Suggestion; +import com.redis.om.spring.repository.query.autocomplete.AutoCompleteOptions; +import redis.clients.jedis.search.FTCreateParams; +import redis.clients.jedis.search.FTSearchParams; +import redis.clients.jedis.search.IndexOptions; +import redis.clients.jedis.search.Query; +import redis.clients.jedis.search.Schema; +import redis.clients.jedis.search.SearchProtocol; +import redis.clients.jedis.search.SearchResult; +import redis.clients.jedis.search.aggr.AggregationBuilder; +import redis.clients.jedis.search.aggr.AggregationResult; +import redis.clients.jedis.search.schemafields.SchemaField; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public interface CommandListener { + default void searchStarted(String indexName, Query q, FTSearchParams params) {} + default void searchFinished(String indexName, Query q, FTSearchParams params, SearchResult searchResult){} + + default void createIndexStarted(String indexName, FTCreateParams params, List fields, Schema schema, IndexOptions options){} + default void createIndexFinished(String indexName, FTCreateParams params, List fields, Schema schema, IndexOptions options, String result){} + + default void aggregateStarted(String indexName, AggregationBuilder q){} + default void aggregateFinished(String indexName, AggregationBuilder q){} + + default void cursorDeleteStarted(String string, long cursorId){} + default void cursorDeleteFinished(String string, long cursorId, String result){} + + default void cursorReadStarted(String string, long cursorId, int count){} + default void cursorReadFinished(String string, long cursorId, int count, AggregationResult aggregationResult){} + + default void explainStarted(String string, Query q){} + default void explainFinished(String string, Query q, String s){} + + default void infoStarted(String string){} + default void infoFinished(String string, Map stringObjectMap){} + + default void dropIndexStarted(String string){} + default void dropIndexFinished(String string, String result){} + + default void dropIndexAndDocumentsStarted(String string){} + default void dropIndexAndDocumentsFinished(String string, String result){} + + default void addSuggestionStarted(String string, String key, String suggestion, double score){} + default void addSuggestionFinished(String string, String key, String suggestion, double score, long result){} + + default void getSuggestionStarted(String string, String key, String prefix, AutoCompleteOptions options){} + default void getSuggestionFinished(String string, String key, String prefix, AutoCompleteOptions options, List list){} + + default void deleteSuggestionStarted(String string, String key, String entry){} + default void deleteSuggestionFinished(String string, String key, String entry, boolean result){} + + default void getSuggestionLengthStarted(String string, String key){} + default void getSuggestionLengthFinished(String string, String key, long result){} + + default void alterIndexStarted(String string, SchemaField[] fields){} + default void alterIndexFinished(String string, SchemaField[] fields, String result){} + + default void setConfigStarted(String string, String option, String value){} + default void setConfigFinished(String string, String option, String value, String result){} + + default void getConfigStarted(String string, String option){} + default void getConfigFinished(String string, String option, Map result){} + + default void getIndexConfigStarted(String string, String option){} + default void getIndexConfigFinished(String string, String option, Map result){} + + default void addAliasStarted(String string, String name){} + default void addAliasFinished(String string, String name, String result){} + + default void updateAliasStarted(String string, String name){} + default void updateAliasFinished(String string, String name, String result){} + + default void deleteAliasStarted(String string, String name){} + default void deleteAliasFinished(String string, String name, String result){} + + default void updateSynonymStarted(String string, String synonymGroupId, String[] terms){} + default void updateSynonymFinished(String string, String synonymGroupId, String[] terms, String result){} + + default void dumpSynonymStarted(String string){} + default void dumpSynonymFinished(String string, Map> result){} + + default void tagValsStarted(String string, String field){} + default void tagValsFinished(String string, String field, Set result){} + + default void commandFailed(SearchProtocol.SearchCommand command, String indexName, Throwable t){} +} diff --git a/redis-om-spring/src/main/java/com/redis/om/spring/ops/RedisModulesOperations.java b/redis-om-spring/src/main/java/com/redis/om/spring/ops/RedisModulesOperations.java index 3539058a..0633c766 100644 --- a/redis-om-spring/src/main/java/com/redis/om/spring/ops/RedisModulesOperations.java +++ b/redis-om-spring/src/main/java/com/redis/om/spring/ops/RedisModulesOperations.java @@ -9,6 +9,7 @@ import com.redis.om.spring.ops.pds.*; import com.redis.om.spring.ops.search.SearchOperations; import com.redis.om.spring.ops.search.SearchOperationsImpl; +import java.util.Optional; /** * A record that provides centralized access to Redis module operations. @@ -26,7 +27,8 @@ * @param client the Redis modules client for executing commands * @param template the Spring Data Redis template for additional Redis operations * @param gsonBuilder the Gson builder for JSON serialization/deserialization configuration - * + * @param commandListener An optional command listener for monitoring Redis commands + * * @author Redis OM Spring Team * @see JSONOperations * @see SearchOperations @@ -37,7 +39,7 @@ * @see TDigestOperations */ public record RedisModulesOperations(RedisModulesClient client, StringRedisTemplate template, - GsonBuilder gsonBuilder) { + GsonBuilder gsonBuilder, Optional commandListener) { /** * Creates and returns operations for interacting with RedisJSON module. @@ -65,7 +67,7 @@ public JSONOperations opsForJSON() { * @return a {@link SearchOperations} instance for search and indexing operations */ public SearchOperations opsForSearch(K index) { - return new SearchOperationsImpl<>(index, client, template); + return new SearchOperationsImpl<>(index, client, template, commandListener); } /** diff --git a/redis-om-spring/src/main/java/com/redis/om/spring/ops/search/SearchOperationsImpl.java b/redis-om-spring/src/main/java/com/redis/om/spring/ops/search/SearchOperationsImpl.java index ba9d706a..7187101b 100644 --- a/redis-om-spring/src/main/java/com/redis/om/spring/ops/search/SearchOperationsImpl.java +++ b/redis-om-spring/src/main/java/com/redis/om/spring/ops/search/SearchOperationsImpl.java @@ -2,8 +2,9 @@ import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; - +import com.redis.om.spring.ops.CommandListener; import org.springframework.data.redis.core.StringRedisTemplate; import com.google.gson.Gson; @@ -39,6 +40,7 @@ public class SearchOperationsImpl implements SearchOperations { private final RedisModulesClient modulesClient; private final K index; private final StringRedisTemplate template; + private final Optional commandListener; /** * Creates a new search operations implementation. @@ -46,77 +48,117 @@ public class SearchOperationsImpl implements SearchOperations { * @param index the search index identifier * @param modulesClient the Redis modules client for search operations * @param template the string Redis template for additional operations + * @param commandListener An optional command listener for monitoring Redis commands */ - public SearchOperationsImpl(K index, RedisModulesClient modulesClient, StringRedisTemplate template) { + public SearchOperationsImpl(K index, RedisModulesClient modulesClient, StringRedisTemplate template, + final Optional commandListener) { this.index = index; this.modulesClient = modulesClient; this.search = modulesClient.clientForSearch(); this.template = template; + this.commandListener = commandListener; } - @Override - public String createIndex(Schema schema, IndexOptions options) { - return search.ftCreate(index.toString(), options, schema); - } + @Override + public String createIndex(Schema schema, IndexOptions options) { + commandListener.ifPresent(it -> it.createIndexStarted(index.toString(), null, null, schema, options)); + final String s = search.ftCreate(index.toString(), options, schema); + commandListener.ifPresent(it -> it.createIndexFinished(index.toString(), null, null, schema, options, s)); + return s; + } - @Override - public String createIndex(FTCreateParams params, List fields) { - return search.ftCreate(index.toString(), params, fields); - } + @Override + public String createIndex(FTCreateParams params, List fields) { + commandListener.ifPresent(it -> it.createIndexStarted(index.toString(), params, fields, null, null)); + final String s = search.ftCreate(index.toString(), params, fields); + commandListener.ifPresent(it -> it.createIndexFinished(index.toString(), params, fields, null, null, s)); + return s; + } - @Override - public SearchResult search(Query q) { - return search.ftSearch(SafeEncoder.encode(index.toString()), q); - } + @Override + @Deprecated + public SearchResult search(Query q) { + commandListener.ifPresent(it -> it.searchStarted(index.toString(), q, null)); + final SearchResult searchResult = search.ftSearch(SafeEncoder.encode(index.toString()), q); + commandListener.ifPresent(it -> it.searchFinished(index.toString(), q, null, searchResult)); + return searchResult; + } - @Override - public SearchResult search(Query q, FTSearchParams params) { - return search.ftSearch(index.toString(), q.toString(), params); - } + @Override + public SearchResult search(Query q, FTSearchParams params) { + commandListener.ifPresent(it -> it.searchStarted(index.toString(), q, null)); + final SearchResult searchResult = search.ftSearch(index.toString(), q.toString(), params); + commandListener.ifPresent(it -> it.searchFinished(index.toString(), q, null, searchResult)); + return searchResult; + } - @Override - public AggregationResult aggregate(AggregationBuilder q) { - return search.ftAggregate(index.toString(), q); - } + @Override + public AggregationResult aggregate(AggregationBuilder q) { + commandListener.ifPresent(it -> it.aggregateStarted(index.toString(), q)); + final AggregationResult aggregationResult = search.ftAggregate(index.toString(), q); + commandListener.ifPresent(it -> it.aggregateFinished(index.toString(), q)); + return aggregationResult; + } - @Override - public String cursorDelete(long cursorId) { - return search.ftCursorDel(index.toString(), cursorId); - } + @Override + public String cursorDelete(long cursorId) { + commandListener.ifPresent(it -> it.cursorDeleteStarted(index.toString(), cursorId)); + final String result = search.ftCursorDel(index.toString(), cursorId); + commandListener.ifPresent(it -> it.cursorDeleteFinished(index.toString(), cursorId, result)); + return result; + } @Override public AggregationResult cursorRead(long cursorId, int count) { - return search.ftCursorRead(index.toString(), cursorId, count); + commandListener.ifPresent(it -> it.cursorReadStarted(index.toString(), cursorId, count)); + final AggregationResult aggregationResult = search.ftCursorRead(index.toString(), cursorId, count); + commandListener.ifPresent(it -> it.cursorReadFinished(index.toString(), cursorId, count, aggregationResult)); + return aggregationResult; } @Override public String explain(Query q) { - return search.ftExplain(index.toString(), q); + commandListener.ifPresent(it -> it.explainStarted(index.toString(), q)); + final String s = search.ftExplain(index.toString(), q); + commandListener.ifPresent(it -> it.explainFinished(index.toString(), q, s)); + return s; } @Override public Map getInfo() { - return search.ftInfo(index.toString()); + commandListener.ifPresent(it -> it.infoStarted(index.toString())); + final Map result = search.ftInfo(index.toString()); + commandListener.ifPresent(it -> it.infoFinished(index.toString(), result)); + return result; } @Override public String dropIndex() { - return search.ftDropIndex(index.toString()); + commandListener.ifPresent(it -> it.dropIndexStarted(index.toString())); + final String result = search.ftDropIndex(index.toString()); + commandListener.ifPresent(it -> it.dropIndexFinished(index.toString(), result)); + return result; } @Override public String dropIndexAndDocuments() { - return search.ftDropIndexDD(index.toString()); + commandListener.ifPresent(it -> it.dropIndexAndDocumentsStarted(index.toString())); + final String result = search.ftDropIndexDD(index.toString()); + commandListener.ifPresent(it -> it.dropIndexAndDocumentsFinished(index.toString(), result)); + return result; } @Override public Long addSuggestion(String key, String suggestion) { - return search.ftSugAdd(key, suggestion, 1.0); + return addSuggestion(key, suggestion, 1.0); } @Override public Long addSuggestion(String key, String suggestion, double score) { - return search.ftSugAdd(key, suggestion, score); + commandListener.ifPresent(it -> it.addSuggestionStarted(index.toString(), key, suggestion, score)); + final long result = search.ftSugAdd(key, suggestion, score); + commandListener.ifPresent(it -> it.addSuggestionFinished(index.toString(), key, suggestion, score, result)); + return result; } @Override @@ -126,101 +168,142 @@ public List getSuggestion(String key, String prefix) { @Override public List getSuggestion(String key, String prefix, AutoCompleteOptions options) { + commandListener.ifPresent(it -> it.getSuggestionStarted(index.toString(), key, prefix, options)); Gson gson = modulesClient.gsonBuilder().create(); if (options.isWithScore()) { List suggestions = search.ftSugGetWithScores(key, prefix, options.isFuzzy(), options.getLimit()); - return suggestions.stream().map(suggestion -> { - if (options.isWithPayload()) { - String[] keyParts = key.split(":"); - String payLoadKey = String.format("sugg:payload:%s:%s", keyParts[keyParts.length - 2], - keyParts[keyParts.length - 1]); - Object payload = template.opsForHash().get(payLoadKey, suggestion); - String json = payload != null ? payload.toString() : "{}"; - Map payloadMap = gson.fromJson(json, new TypeToken>() { - }.getType()); - return new Suggestion(suggestion.getElement(), suggestion.getScore(), payloadMap); - } else { - return new Suggestion(suggestion.getElement(), suggestion.getScore()); - } - }).toList(); + List list = suggestions.stream().map(suggestion -> { + if (options.isWithPayload()) { + String[] keyParts = key.split(":"); + String payLoadKey = String.format("sugg:payload:%s:%s", keyParts[keyParts.length - 2], + keyParts[keyParts.length - 1]); + Object payload = template.opsForHash().get(payLoadKey, suggestion); + String json = payload != null ? payload.toString() : "{}"; + Map payloadMap = gson.fromJson(json, new TypeToken>() { + }.getType()); + return new Suggestion(suggestion.getElement(), suggestion.getScore(), payloadMap); + } else { + return new Suggestion(suggestion.getElement(), suggestion.getScore()); + } + }).toList(); + commandListener.ifPresent(it -> it.getSuggestionFinished(index.toString(), key, prefix, options, list)); + return list; } else { List suggestions = search.ftSugGet(key, prefix, options.isFuzzy(), options.getLimit()); - return suggestions.stream().map(suggestion -> { - if (options.isWithPayload()) { - String[] keyParts = key.split(":"); - String payLoadKey = String.format("sugg:payload:%s:%s", keyParts[keyParts.length - 2], - keyParts[keyParts.length - 1]); - Object payload = template.opsForHash().get(payLoadKey, suggestion); - String json = payload != null ? payload.toString() : "{}"; - Map payloadMap = gson.fromJson(json, new TypeToken>() { - }.getType()); - return new Suggestion(suggestion, payloadMap); - } else { - return new Suggestion(suggestion); - } - }).toList(); + List list = suggestions.stream().map(suggestion -> { + if (options.isWithPayload()) { + String[] keyParts = key.split(":"); + String payLoadKey = String.format("sugg:payload:%s:%s", keyParts[keyParts.length - 2], + keyParts[keyParts.length - 1]); + Object payload = template.opsForHash().get(payLoadKey, suggestion); + String json = payload != null ? payload.toString() : "{}"; + Map payloadMap = gson.fromJson(json, new TypeToken>() { + }.getType()); + return new Suggestion(suggestion, payloadMap); + } else { + return new Suggestion(suggestion); + } + }).toList(); + commandListener.ifPresent(it -> it.getSuggestionFinished(index.toString(), key, prefix, options, list)); + return list; } } @Override public Boolean deleteSuggestion(String key, String entry) { - return search.ftSugDel(key, entry); + commandListener.ifPresent(it -> it.deleteSuggestionStarted(index.toString(), key, entry)); + final boolean result = search.ftSugDel(key, entry); + commandListener.ifPresent(it -> it.deleteSuggestionFinished(index.toString(), key, entry, result)); + return result; } @Override public Long getSuggestionLength(String key) { - return search.ftSugLen(key); + commandListener.ifPresent(it -> it.getSuggestionLengthStarted(index.toString(), key)); + final long result = search.ftSugLen(key); + commandListener.ifPresent(it -> it.getSuggestionLengthFinished(index.toString(), key, result)); + return result; } @Override public String alterIndex(SchemaField... fields) { - return search.ftAlter(index.toString(), fields); + commandListener.ifPresent(it -> it.alterIndexStarted(index.toString(), fields)); + final String result = search.ftAlter(index.toString(), fields); + commandListener.ifPresent(it -> it.alterIndexFinished(index.toString(), fields, result)); + return result; } @Override public String setConfig(String option, String value) { - return search.ftConfigSet(option, value); + commandListener.ifPresent(it -> it.setConfigStarted(index.toString(), option, value)); + final String result = search.ftConfigSet(option, value); + commandListener.ifPresent(it -> it.setConfigFinished(index.toString(), option, value, result)); + return result; } @Override public Map getConfig(String option) { - return search.ftConfigGet(option); + commandListener.ifPresent(it -> it.getConfigStarted(index.toString(), option)); + final Map result = search.ftConfigGet(option); + commandListener.ifPresent(it -> it.getConfigFinished(index.toString(), option, result)); + return result; } @Override public Map getIndexConfig(String option) { - return search.ftConfigGet(index.toString(), option); + commandListener.ifPresent(it -> it.getIndexConfigStarted(index.toString(), option)); + final Map result = search.ftConfigGet(index.toString(), option); + commandListener.ifPresent(it -> it.getIndexConfigFinished(index.toString(), option, result)); + return result; } @Override public String addAlias(String name) { - return search.ftAliasAdd(name, index.toString()); + commandListener.ifPresent(it -> it.addAliasStarted(index.toString(), name)); + final String result = search.ftAliasAdd(name, index.toString()); + commandListener.ifPresent(it -> it.addAliasFinished(index.toString(), name, result)); + return result; } @Override public String updateAlias(String name) { - return search.ftAliasUpdate(name, index.toString()); + commandListener.ifPresent(it -> it.updateAliasStarted(index.toString(), name)); + final String result = search.ftAliasUpdate(name, index.toString()); + commandListener.ifPresent(it -> it.updateAliasFinished(index.toString(), name, result)); + return result; } @Override public String deleteAlias(String name) { - return search.ftAliasDel(name); + commandListener.ifPresent(it -> it.deleteAliasStarted(index.toString(), name)); + final String result = search.ftAliasDel(name); + commandListener.ifPresent(it -> it.deleteAliasFinished(index.toString(), name, result)); + return result; } @Override public String updateSynonym(String synonymGroupId, String... terms) { - return search.ftSynUpdate(index.toString(), synonymGroupId, terms); + commandListener.ifPresent(it -> it.updateSynonymStarted(index.toString(), synonymGroupId, terms)); + final String result = search.ftSynUpdate(index.toString(), synonymGroupId, terms); + commandListener.ifPresent(it -> it.updateSynonymFinished(index.toString(), synonymGroupId, terms, result)); + return result; } @Override public Map> dumpSynonym() { - return search.ftSynDump(index.toString()); + commandListener.ifPresent(it -> it.dumpSynonymStarted(index.toString())); + final Map> result = search.ftSynDump(index.toString()); + commandListener.ifPresent(it -> it.dumpSynonymFinished(index.toString(), result)); + return result; } @Override public Set tagVals(String field) { - return search.ftTagVals(index.toString(), field); + commandListener.ifPresent(it -> it.tagValsStarted(index.toString(), field)); + final Set result = search.ftTagVals(index.toString(), field); + commandListener.ifPresent(it -> it.tagValsFinished(index.toString(), field, result)); + return result; } } From 89e1482fee6bd8b21a5b830b4050cf5e582d7ab9 Mon Sep 17 00:00:00 2001 From: "TURKCELL\\TCASENOCAK" Date: Fri, 10 Oct 2025 08:38:57 +0300 Subject: [PATCH 2/2] feat: add CommandListener support and NoOpCommandListener implementation for Redis command monitoring --- .../om/spring/RedisModulesConfiguration.java | 25 +++- .../om/spring/ops/NoOpCommandListener.java | 7 ++ .../om/spring/ops/RedisModulesOperations.java | 5 +- .../ops/search/SearchOperationsImpl.java | 109 +++++++++--------- 4 files changed, 86 insertions(+), 60 deletions(-) create mode 100644 redis-om-spring/src/main/java/com/redis/om/spring/ops/NoOpCommandListener.java diff --git a/redis-om-spring/src/main/java/com/redis/om/spring/RedisModulesConfiguration.java b/redis-om-spring/src/main/java/com/redis/om/spring/RedisModulesConfiguration.java index f866b479..edc522e2 100644 --- a/redis-om-spring/src/main/java/com/redis/om/spring/RedisModulesConfiguration.java +++ b/redis-om-spring/src/main/java/com/redis/om/spring/RedisModulesConfiguration.java @@ -8,6 +8,8 @@ import java.util.List; import java.util.Set; +import com.redis.om.spring.ops.CommandListener; +import com.redis.om.spring.ops.NoOpCommandListener; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -202,6 +204,7 @@ RedisModulesClient redisModulesClient( // * @param rmc the Redis modules client for low-level access * @param template the string Redis template for basic operations * @param gsonBuilder the Gson builder for JSON serialization + * @param commandListener a command listener for monitoring Redis commands * @return the Redis modules operations instance */ @Bean( @@ -215,10 +218,28 @@ RedisModulesOperations redisModulesOperations( // StringRedisTemplate template, // @Qualifier( "omGsonBuilder" - ) GsonBuilder gsonBuilder) { - return new RedisModulesOperations<>(rmc, template, gsonBuilder); + ) GsonBuilder gsonBuilder, final CommandListener commandListener) { + return new RedisModulesOperations<>(rmc, template, gsonBuilder, commandListener); } + /** + * Provides a default implementation of the CommandListener bean. + *

+ * This method creates a no-operation (NoOp) implementation of the CommandListener interface. + * It is used as a fallback when no other CommandListener bean is defined in the application context. + *

+ * The {@code @Fallback} annotation ensures that this bean is only used when no other + * CommandListener bean is available, allowing developers to override it with a custom implementation if needed. + * + * @return a NoOpCommandListener instance, which performs no operations. + */ + @Bean + @Fallback + public CommandListener commandListener() { + return new NoOpCommandListener(); + } + + /** * Creates the JSON operations bean for RedisJSON commands. *

diff --git a/redis-om-spring/src/main/java/com/redis/om/spring/ops/NoOpCommandListener.java b/redis-om-spring/src/main/java/com/redis/om/spring/ops/NoOpCommandListener.java new file mode 100644 index 00000000..170e6125 --- /dev/null +++ b/redis-om-spring/src/main/java/com/redis/om/spring/ops/NoOpCommandListener.java @@ -0,0 +1,7 @@ +package com.redis.om.spring.ops; + +import org.springframework.stereotype.Component; + +@Component +public class NoOpCommandListener implements CommandListener { +} diff --git a/redis-om-spring/src/main/java/com/redis/om/spring/ops/RedisModulesOperations.java b/redis-om-spring/src/main/java/com/redis/om/spring/ops/RedisModulesOperations.java index 0633c766..19c564ba 100644 --- a/redis-om-spring/src/main/java/com/redis/om/spring/ops/RedisModulesOperations.java +++ b/redis-om-spring/src/main/java/com/redis/om/spring/ops/RedisModulesOperations.java @@ -9,7 +9,6 @@ import com.redis.om.spring.ops.pds.*; import com.redis.om.spring.ops.search.SearchOperations; import com.redis.om.spring.ops.search.SearchOperationsImpl; -import java.util.Optional; /** * A record that provides centralized access to Redis module operations. @@ -27,7 +26,7 @@ * @param client the Redis modules client for executing commands * @param template the Spring Data Redis template for additional Redis operations * @param gsonBuilder the Gson builder for JSON serialization/deserialization configuration - * @param commandListener An optional command listener for monitoring Redis commands + * @param commandListener A command listener for monitoring Redis commands * * @author Redis OM Spring Team * @see JSONOperations @@ -39,7 +38,7 @@ * @see TDigestOperations */ public record RedisModulesOperations(RedisModulesClient client, StringRedisTemplate template, - GsonBuilder gsonBuilder, Optional commandListener) { + GsonBuilder gsonBuilder, CommandListener commandListener) { /** * Creates and returns operations for interacting with RedisJSON module. diff --git a/redis-om-spring/src/main/java/com/redis/om/spring/ops/search/SearchOperationsImpl.java b/redis-om-spring/src/main/java/com/redis/om/spring/ops/search/SearchOperationsImpl.java index 7187101b..1c77e90f 100644 --- a/redis-om-spring/src/main/java/com/redis/om/spring/ops/search/SearchOperationsImpl.java +++ b/redis-om-spring/src/main/java/com/redis/om/spring/ops/search/SearchOperationsImpl.java @@ -2,7 +2,6 @@ import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; import com.redis.om.spring.ops.CommandListener; import org.springframework.data.redis.core.StringRedisTemplate; @@ -40,7 +39,7 @@ public class SearchOperationsImpl implements SearchOperations { private final RedisModulesClient modulesClient; private final K index; private final StringRedisTemplate template; - private final Optional commandListener; + private final CommandListener commandListener; /** * Creates a new search operations implementation. @@ -48,10 +47,10 @@ public class SearchOperationsImpl implements SearchOperations { * @param index the search index identifier * @param modulesClient the Redis modules client for search operations * @param template the string Redis template for additional operations - * @param commandListener An optional command listener for monitoring Redis commands + * @param commandListener A command listener for monitoring Redis commands */ public SearchOperationsImpl(K index, RedisModulesClient modulesClient, StringRedisTemplate template, - final Optional commandListener) { + final CommandListener commandListener) { this.index = index; this.modulesClient = modulesClient; this.search = modulesClient.clientForSearch(); @@ -61,90 +60,90 @@ public SearchOperationsImpl(K index, RedisModulesClient modulesClient, StringRed @Override public String createIndex(Schema schema, IndexOptions options) { - commandListener.ifPresent(it -> it.createIndexStarted(index.toString(), null, null, schema, options)); + commandListener.createIndexStarted(index.toString(), null, null, schema, options); final String s = search.ftCreate(index.toString(), options, schema); - commandListener.ifPresent(it -> it.createIndexFinished(index.toString(), null, null, schema, options, s)); + commandListener.createIndexFinished(index.toString(), null, null, schema, options, s); return s; } @Override public String createIndex(FTCreateParams params, List fields) { - commandListener.ifPresent(it -> it.createIndexStarted(index.toString(), params, fields, null, null)); + commandListener.createIndexStarted(index.toString(), params, fields, null, null); final String s = search.ftCreate(index.toString(), params, fields); - commandListener.ifPresent(it -> it.createIndexFinished(index.toString(), params, fields, null, null, s)); + commandListener.createIndexFinished(index.toString(), params, fields, null, null, s); return s; } @Override @Deprecated public SearchResult search(Query q) { - commandListener.ifPresent(it -> it.searchStarted(index.toString(), q, null)); + commandListener.searchStarted(index.toString(), q, null); final SearchResult searchResult = search.ftSearch(SafeEncoder.encode(index.toString()), q); - commandListener.ifPresent(it -> it.searchFinished(index.toString(), q, null, searchResult)); + commandListener.searchFinished(index.toString(), q, null, searchResult); return searchResult; } @Override public SearchResult search(Query q, FTSearchParams params) { - commandListener.ifPresent(it -> it.searchStarted(index.toString(), q, null)); + commandListener.searchStarted(index.toString(), q, null); final SearchResult searchResult = search.ftSearch(index.toString(), q.toString(), params); - commandListener.ifPresent(it -> it.searchFinished(index.toString(), q, null, searchResult)); + commandListener.searchFinished(index.toString(), q, null, searchResult); return searchResult; } @Override public AggregationResult aggregate(AggregationBuilder q) { - commandListener.ifPresent(it -> it.aggregateStarted(index.toString(), q)); + commandListener.aggregateStarted(index.toString(), q); final AggregationResult aggregationResult = search.ftAggregate(index.toString(), q); - commandListener.ifPresent(it -> it.aggregateFinished(index.toString(), q)); + commandListener.aggregateFinished(index.toString(), q); return aggregationResult; } @Override public String cursorDelete(long cursorId) { - commandListener.ifPresent(it -> it.cursorDeleteStarted(index.toString(), cursorId)); + commandListener.cursorDeleteStarted(index.toString(), cursorId); final String result = search.ftCursorDel(index.toString(), cursorId); - commandListener.ifPresent(it -> it.cursorDeleteFinished(index.toString(), cursorId, result)); + commandListener.cursorDeleteFinished(index.toString(), cursorId, result); return result; } @Override public AggregationResult cursorRead(long cursorId, int count) { - commandListener.ifPresent(it -> it.cursorReadStarted(index.toString(), cursorId, count)); + commandListener.cursorReadStarted(index.toString(), cursorId, count); final AggregationResult aggregationResult = search.ftCursorRead(index.toString(), cursorId, count); - commandListener.ifPresent(it -> it.cursorReadFinished(index.toString(), cursorId, count, aggregationResult)); + commandListener.cursorReadFinished(index.toString(), cursorId, count, aggregationResult); return aggregationResult; } @Override public String explain(Query q) { - commandListener.ifPresent(it -> it.explainStarted(index.toString(), q)); + commandListener.explainStarted(index.toString(), q); final String s = search.ftExplain(index.toString(), q); - commandListener.ifPresent(it -> it.explainFinished(index.toString(), q, s)); + commandListener.explainFinished(index.toString(), q, s); return s; } @Override public Map getInfo() { - commandListener.ifPresent(it -> it.infoStarted(index.toString())); + commandListener.infoStarted(index.toString()); final Map result = search.ftInfo(index.toString()); - commandListener.ifPresent(it -> it.infoFinished(index.toString(), result)); + commandListener.infoFinished(index.toString(), result); return result; } @Override public String dropIndex() { - commandListener.ifPresent(it -> it.dropIndexStarted(index.toString())); + commandListener.dropIndexStarted(index.toString()); final String result = search.ftDropIndex(index.toString()); - commandListener.ifPresent(it -> it.dropIndexFinished(index.toString(), result)); + commandListener.dropIndexFinished(index.toString(), result); return result; } @Override public String dropIndexAndDocuments() { - commandListener.ifPresent(it -> it.dropIndexAndDocumentsStarted(index.toString())); + commandListener.dropIndexAndDocumentsStarted(index.toString()); final String result = search.ftDropIndexDD(index.toString()); - commandListener.ifPresent(it -> it.dropIndexAndDocumentsFinished(index.toString(), result)); + commandListener.dropIndexAndDocumentsFinished(index.toString(), result); return result; } @@ -155,9 +154,9 @@ public Long addSuggestion(String key, String suggestion) { @Override public Long addSuggestion(String key, String suggestion, double score) { - commandListener.ifPresent(it -> it.addSuggestionStarted(index.toString(), key, suggestion, score)); + commandListener.addSuggestionStarted(index.toString(), key, suggestion, score); final long result = search.ftSugAdd(key, suggestion, score); - commandListener.ifPresent(it -> it.addSuggestionFinished(index.toString(), key, suggestion, score, result)); + commandListener.addSuggestionFinished(index.toString(), key, suggestion, score, result); return result; } @@ -168,7 +167,7 @@ public List getSuggestion(String key, String prefix) { @Override public List getSuggestion(String key, String prefix, AutoCompleteOptions options) { - commandListener.ifPresent(it -> it.getSuggestionStarted(index.toString(), key, prefix, options)); + commandListener.getSuggestionStarted(index.toString(), key, prefix, options); Gson gson = modulesClient.gsonBuilder().create(); if (options.isWithScore()) { @@ -187,7 +186,7 @@ public List getSuggestion(String key, String prefix, AutoCompleteOpt return new Suggestion(suggestion.getElement(), suggestion.getScore()); } }).toList(); - commandListener.ifPresent(it -> it.getSuggestionFinished(index.toString(), key, prefix, options, list)); + commandListener.getSuggestionFinished(index.toString(), key, prefix, options, list); return list; } else { List suggestions = search.ftSugGet(key, prefix, options.isFuzzy(), options.getLimit()); @@ -205,104 +204,104 @@ public List getSuggestion(String key, String prefix, AutoCompleteOpt return new Suggestion(suggestion); } }).toList(); - commandListener.ifPresent(it -> it.getSuggestionFinished(index.toString(), key, prefix, options, list)); + commandListener.getSuggestionFinished(index.toString(), key, prefix, options, list); return list; } } @Override public Boolean deleteSuggestion(String key, String entry) { - commandListener.ifPresent(it -> it.deleteSuggestionStarted(index.toString(), key, entry)); + commandListener.deleteSuggestionStarted(index.toString(), key, entry); final boolean result = search.ftSugDel(key, entry); - commandListener.ifPresent(it -> it.deleteSuggestionFinished(index.toString(), key, entry, result)); + commandListener.deleteSuggestionFinished(index.toString(), key, entry, result); return result; } @Override public Long getSuggestionLength(String key) { - commandListener.ifPresent(it -> it.getSuggestionLengthStarted(index.toString(), key)); + commandListener.getSuggestionLengthStarted(index.toString(), key); final long result = search.ftSugLen(key); - commandListener.ifPresent(it -> it.getSuggestionLengthFinished(index.toString(), key, result)); + commandListener.getSuggestionLengthFinished(index.toString(), key, result); return result; } @Override public String alterIndex(SchemaField... fields) { - commandListener.ifPresent(it -> it.alterIndexStarted(index.toString(), fields)); + commandListener.alterIndexStarted(index.toString(), fields); final String result = search.ftAlter(index.toString(), fields); - commandListener.ifPresent(it -> it.alterIndexFinished(index.toString(), fields, result)); + commandListener.alterIndexFinished(index.toString(), fields, result); return result; } @Override public String setConfig(String option, String value) { - commandListener.ifPresent(it -> it.setConfigStarted(index.toString(), option, value)); + commandListener.setConfigStarted(index.toString(), option, value); final String result = search.ftConfigSet(option, value); - commandListener.ifPresent(it -> it.setConfigFinished(index.toString(), option, value, result)); + commandListener.setConfigFinished(index.toString(), option, value, result); return result; } @Override public Map getConfig(String option) { - commandListener.ifPresent(it -> it.getConfigStarted(index.toString(), option)); + commandListener.getConfigStarted(index.toString(), option); final Map result = search.ftConfigGet(option); - commandListener.ifPresent(it -> it.getConfigFinished(index.toString(), option, result)); + commandListener.getConfigFinished(index.toString(), option, result); return result; } @Override public Map getIndexConfig(String option) { - commandListener.ifPresent(it -> it.getIndexConfigStarted(index.toString(), option)); + commandListener.getIndexConfigStarted(index.toString(), option); final Map result = search.ftConfigGet(index.toString(), option); - commandListener.ifPresent(it -> it.getIndexConfigFinished(index.toString(), option, result)); + commandListener.getIndexConfigFinished(index.toString(), option, result); return result; } @Override public String addAlias(String name) { - commandListener.ifPresent(it -> it.addAliasStarted(index.toString(), name)); + commandListener.addAliasStarted(index.toString(), name); final String result = search.ftAliasAdd(name, index.toString()); - commandListener.ifPresent(it -> it.addAliasFinished(index.toString(), name, result)); + commandListener.addAliasFinished(index.toString(), name, result); return result; } @Override public String updateAlias(String name) { - commandListener.ifPresent(it -> it.updateAliasStarted(index.toString(), name)); + commandListener.updateAliasStarted(index.toString(), name); final String result = search.ftAliasUpdate(name, index.toString()); - commandListener.ifPresent(it -> it.updateAliasFinished(index.toString(), name, result)); + commandListener.updateAliasFinished(index.toString(), name, result); return result; } @Override public String deleteAlias(String name) { - commandListener.ifPresent(it -> it.deleteAliasStarted(index.toString(), name)); + commandListener.deleteAliasStarted(index.toString(), name); final String result = search.ftAliasDel(name); - commandListener.ifPresent(it -> it.deleteAliasFinished(index.toString(), name, result)); + commandListener.deleteAliasFinished(index.toString(), name, result); return result; } @Override public String updateSynonym(String synonymGroupId, String... terms) { - commandListener.ifPresent(it -> it.updateSynonymStarted(index.toString(), synonymGroupId, terms)); + commandListener.updateSynonymStarted(index.toString(), synonymGroupId, terms); final String result = search.ftSynUpdate(index.toString(), synonymGroupId, terms); - commandListener.ifPresent(it -> it.updateSynonymFinished(index.toString(), synonymGroupId, terms, result)); + commandListener.updateSynonymFinished(index.toString(), synonymGroupId, terms, result); return result; } @Override public Map> dumpSynonym() { - commandListener.ifPresent(it -> it.dumpSynonymStarted(index.toString())); + commandListener.dumpSynonymStarted(index.toString()); final Map> result = search.ftSynDump(index.toString()); - commandListener.ifPresent(it -> it.dumpSynonymFinished(index.toString(), result)); + commandListener.dumpSynonymFinished(index.toString(), result); return result; } @Override public Set tagVals(String field) { - commandListener.ifPresent(it -> it.tagValsStarted(index.toString(), field)); + commandListener.tagValsStarted(index.toString(), field); final Set result = search.ftTagVals(index.toString(), field); - commandListener.ifPresent(it -> it.tagValsFinished(index.toString(), field, result)); + commandListener.tagValsFinished(index.toString(), field, result); return result; }