Skip to content

fix: rework search API generics to replace unnecessary type params with String#3716

Open
viktoriya-kutsarova wants to merge 9 commits into
redis:mainfrom
viktoriya-kutsarova:rework-codecs-for-redis-search-module
Open

fix: rework search API generics to replace unnecessary type params with String#3716
viktoriya-kutsarova wants to merge 9 commits into
redis:mainfrom
viktoriya-kutsarova:rework-codecs-for-redis-search-module

Conversation

@viktoriya-kutsarova
Copy link
Copy Markdown
Contributor

@viktoriya-kutsarova viktoriya-kutsarova commented Apr 7, 2026

Summary

Reworks the generics across the RediSearch API to remove unnecessary type parameter exposure and replace them with String where values were never codec-encoded in the first place. Fixes incorrect codec usage in warning decoding across both search parsers.

Changes

Arguments classes — K and V removed

The following argument classes were fully de-genericized. All fields and builder methods that previously carried K or V become String, since they represent schema attribute names, filter expressions, stop words, prefixes, and other index-definition strings that are always UTF-8 text:

  • CreateArgs<K, V>CreateArgs (prefixes, filter, language field, score field, payload field, stop words)
  • FieldArgs<K>FieldArgs (field name, alias); all concrete subclasses follow: GeoFieldArgs, GeoshapeFieldArgs, NumericFieldArgs, TagFieldArgs, TextFieldArgs, VectorFieldArgs
  • ExplainArgs<K, V>ExplainArgs
  • SpellCheckArgs<K, V>SpellCheckArgs
  • SynUpdateArgs<K, V>SynUpdateArgs
  • SugAddArgs<K, V>SugAddArgs
  • SugGetArgs<K, V>SugGetArgs
  • HybridArgs<K, V>HybridArgs
  • HighlightArgs<K, V>HighlightArgs<K>V removed (tags become String); K is retained because highlight fields are hash field identifiers, consistent with hget(K key, K field). Tags<V>Tags, addValue()add() in build()

AggregateArgs<K, V>AggregateArgs<K>

V is removed entirely. Inside AggregateArgs, K is narrowed to LoadField only, since hash field identifiers are legitimately typed as K. As a consequence:

  • LoadField.field is now correctly encoded via args.addKey() instead of the previous .toString() bypass; LoadField.alias becomes String
  • All pipeline labels (Apply.name, Reducer.alias, GroupBy.properties, SortProperty.property, param keys) become String
  • GroupBy, SortBy, SortProperty, Apply, Reducer, Filter, Limit and PipelineOperation are now non-generic with build() signatures narrowed from CommandArgs<K, ?> to CommandArgs<?, ?>

SearchReply and HybridReply warnings

warnings: List<V>List<String> in both classes. Server-generated warning messages are always UTF-8 text and must not be decoded through the user-configured value codec. SearchReplyParser and HybridReplyParser are updated to use StringCodec.UTF8.decodeValue() at all warning-decoding sites — including both the RESP2 and RESP3 paths in HybridReplyParser, which had the same bug in two separate places.

Command interfaces and implementations

All method signatures updated across the full command surface:

  • Sync: RediSearchCommands
  • Async: RediSearchAsyncCommands
  • Reactive: RediSearchReactiveCommands
  • Cluster variants of all three
  • AbstractRedisAsyncCommands, AbstractRedisReactiveCommands, RediSearchCommandBuilder
  • Kotlin coroutine wrappers

Javadoc corrections

  • Class-level examples in AggregateArgs corrected: wrong return type (SearchReplyAggregationReply), stale generic witnesses, invalid load() varargs call, and .reduce() chained directly on Builder instead of GroupBy
  • WithCursor factory method Javadocs corrected: were copy-pasted from Apply with wrong @param descriptions and @return text
  • filter() builder example corrected for the same .reduce() on Builder mistake

Testing

  • All existing tests updated to reflect the new signatures
  • Integration test testSearchWarningsReturnedAsStrings added to RediSearchIntegrationTests, verifying that getWarnings() returns List<String>, that the list is non-null for normal searches, and that any warning content produced under a 1 ms timeout is correctly decoded as a non-empty UTF-8 string
  • Existing weak assertion on HybridReply.getWarnings() (size() >= 0) replaced with a typed List<String> assignment and per-element content validation

Note

Medium Risk
Public RediSearch command signatures are changed broadly (sync/async/reactive/cluster/builders), which is a source-compatible breaking change for clients and could affect downstream compilation and behavior. Runtime risk is moderate and mainly limited to parsing/encoding of RediSearch protocol literals (queries, warnings, dict/synonyms).

Overview
This PR reworks the RediSearch Java API types to stop treating query/dictionary/synonym/index metadata as user V values, replacing those parameters/return types with String across command interfaces and implementations (sync/async/reactive and cluster), and updating RediSearchCommandBuilder accordingly (e.g., ftSearch/ftAggregate/ftExplain/ftSpellcheck, dict/synonym ops, ftList).

It also fixes warning decoding in SearchReplyParser/HybridReplyParser and changes SearchReply/HybridReply warnings to List<String> so server warnings are decoded via StringCodec.UTF8 instead of the user value codec; SpellCheckResult is de-genericized to String-based terms/suggestions. Minor repo hygiene: .gitignore now ignores .augment and correctly matches .vscode*.

Reviewed by Cursor Bugbot for commit bb65286. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread src/main/java/io/lettuce/core/search/arguments/CreateArgs.java
@viktoriya-kutsarova viktoriya-kutsarova force-pushed the rework-codecs-for-redis-search-module branch from aca713c to aeb5532 Compare April 8, 2026 12:38
Comment thread src/main/java/io/lettuce/core/search/arguments/AggregateArgs.java Outdated
@viktoriya-kutsarova viktoriya-kutsarova force-pushed the rework-codecs-for-redis-search-module branch from aeb5532 to eecece8 Compare April 9, 2026 13:58
Comment thread src/main/java/io/lettuce/core/search/arguments/AggregateArgs.java Outdated
@viktoriya-kutsarova viktoriya-kutsarova force-pushed the rework-codecs-for-redis-search-module branch 4 times, most recently from 9c29c1c to 5300e85 Compare April 14, 2026 20:45
@viktoriya-kutsarova viktoriya-kutsarova force-pushed the rework-codecs-for-redis-search-module branch 2 times, most recently from 59689ba to 7230ad5 Compare April 20, 2026 12:17
@viktoriya-kutsarova viktoriya-kutsarova force-pushed the rework-codecs-for-redis-search-module branch from 7230ad5 to 7c19f36 Compare April 20, 2026 14:16
Copy link
Copy Markdown
Collaborator

@tishun tishun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

(best effort since it as a huge review)

Comment on lines +371 to +374
* @deprecated {@code FT.TAGVALS} has been deprecated by Redis. See
* <a href="https://redis.io/docs/latest/commands/ft.tagvals/">FT.TAGVALS</a>.
*/
@Deprecated
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@a-TODO-rov TBH I am wondering if we should not just remove this. Perhaps @uglide can help us understand if there is a use case for keeping it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @tishun for pointing this out. I will check with @uglide.

Comment thread src/main/java/io/lettuce/core/search/arguments/AggregateArgs.java Outdated
* AggregateArgs<String, String> args = AggregateArgs.<String, String> builder().groupBy("category")
* .reduce(Reducer.count().as("count")).sortBy("count", SortDirection.DESC).build();
* SearchReply<String, String> result = redis.ftAggregate("myindex", "*", args);
* AggregateArgs<String> args = AggregateArgs.builder().groupBy(GroupBy.of("category").reduce(Reducer.count().as("count")))
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason the AI agent has changed the groupBy notation from groupBy("category") to groupBy(GroupBy.of("category").

* AggregateArgs<String, String> args = AggregateArgs.<String, String> builder().load("price", "quantity", "category")
* .apply("@price * @quantity", "total_value").filter("@total_value > 100").groupBy("category")
* .reduce(Reducer.sum("@total_value").as("category_total")).reduce(Reducer.avg("@price").as("avg_price"))
* AggregateArgs<String> args = AggregateArgs.builder().load("price").load("quantity").load("category")
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AI agent has changed the example from load("price", "quantity", "category") to load("price").load("quantity").load("category").

@viktoriya-kutsarova viktoriya-kutsarova force-pushed the rework-codecs-for-redis-search-module branch from 0eeb412 to cf48a11 Compare April 21, 2026 14:37
@viktoriya-kutsarova viktoriya-kutsarova force-pushed the rework-codecs-for-redis-search-module branch from cf48a11 to fd16d95 Compare April 22, 2026 14:23
Comment thread src/main/java/io/lettuce/core/RediSearchCommandBuilder.java Outdated
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 0786cd8. Configure here.

Comment thread src/main/java/io/lettuce/core/search/SearchReplyParser.java
@viktoriya-kutsarova viktoriya-kutsarova force-pushed the rework-codecs-for-redis-search-module branch 2 times, most recently from 1564fff to 5a0215e Compare April 30, 2026 12:50
@viktoriya-kutsarova viktoriya-kutsarova force-pushed the rework-codecs-for-redis-search-module branch from 5a0215e to f93e2e7 Compare April 30, 2026 13:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants