Skip to content

Commit 04005cb

Browse files
Support Resp 3 Redis Search Unstable Mode (#3098)
* Updated module version that points to retracted package version (#3074) * Updated module version that points to retracted package version * Updated testing image to latest * support raw parsing for problematic Redis Search types * Add UnstableResp3SearchModule to client options * Add tests for Resp3 Search unstable mode * Add tests for Resp3 Search unstable mode * Add readme note * Add words to spellcheck * Add UnstableResp3SearchModule check to assertStableCommand * Fix assertStableCommand logic * remove go.mod changes * Check panic occur on tests * rename method * update errors * Rename flag to UnstableResp3 --------- Co-authored-by: Vladyslav Vildanov <[email protected]> Co-authored-by: vladvildanov <[email protected]>
1 parent 9f6171d commit 04005cb

10 files changed

+273
-9
lines changed

.github/wordlist.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
ACLs
2+
APIs
23
autoload
34
autoloader
45
autoloading
@@ -46,9 +47,11 @@ runtime
4647
SHA
4748
sharding
4849
SETNAME
50+
SpellCheck
4951
SSL
5052
struct
5153
stunnel
54+
SynDump
5255
TCP
5356
TLS
5457
uri

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ rdb := redis.NewClient(&redis.Options{
183183
})
184184
```
185185

186+
#### Unstable RESP3 Structures for RediSearch Commands
187+
When integrating Redis with application functionalities using RESP3, it's important to note that some response structures aren't final yet. This is especially true for more complex structures like search and query results. We recommend using RESP2 when using the search and query capabilities, but we plan to stabilize the RESP3-based API-s in the coming versions. You can find more guidance in the upcoming release notes.
188+
186189
## Contributing
187190

188191
Please see [out contributing guidelines](CONTRIBUTING.md) to help us improve this library!

command.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ type Cmder interface {
4040

4141
readTimeout() *time.Duration
4242
readReply(rd *proto.Reader) error
43-
43+
readRawReply(rd *proto.Reader) error
4444
SetErr(error)
4545
Err() error
4646
}
@@ -122,11 +122,11 @@ func cmdString(cmd Cmder, val interface{}) string {
122122
//------------------------------------------------------------------------------
123123

124124
type baseCmd struct {
125-
ctx context.Context
126-
args []interface{}
127-
err error
128-
keyPos int8
129-
125+
ctx context.Context
126+
args []interface{}
127+
err error
128+
keyPos int8
129+
rawVal interface{}
130130
_readTimeout *time.Duration
131131
}
132132

@@ -197,6 +197,11 @@ func (cmd *baseCmd) setReadTimeout(d time.Duration) {
197197
cmd._readTimeout = &d
198198
}
199199

200+
func (cmd *baseCmd) readRawReply(rd *proto.Reader) (err error) {
201+
cmd.rawVal, err = rd.ReadReply()
202+
return err
203+
}
204+
200205
//------------------------------------------------------------------------------
201206

202207
type Cmd struct {

options.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ type Options struct {
153153

154154
// Add suffix to client name. Default is empty.
155155
IdentitySuffix string
156+
157+
// Enable Unstable mode for Redis Search module with RESP3.
158+
UnstableResp3 bool
156159
}
157160

158161
func (opt *Options) init() {

redis.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,19 @@ func (c *baseClient) process(ctx context.Context, cmd Cmder) error {
412412
return lastErr
413413
}
414414

415+
func (c *baseClient) assertUnstableCommand(cmd Cmder) bool {
416+
switch cmd.(type) {
417+
case *AggregateCmd, *FTInfoCmd, *FTSpellCheckCmd, *FTSearchCmd, *FTSynDumpCmd:
418+
if c.opt.UnstableResp3 {
419+
return true
420+
} else {
421+
panic("RESP3 responses for this command are disabled because they may still change. Please set the flag UnstableResp3 . See the [README](https://github.com/redis/go-redis/blob/master/README.md) and the release notes for guidance.")
422+
}
423+
default:
424+
return false
425+
}
426+
}
427+
415428
func (c *baseClient) _process(ctx context.Context, cmd Cmder, attempt int) (bool, error) {
416429
if attempt > 0 {
417430
if err := internal.Sleep(ctx, c.retryBackoff(attempt)); err != nil {
@@ -427,8 +440,12 @@ func (c *baseClient) _process(ctx context.Context, cmd Cmder, attempt int) (bool
427440
atomic.StoreUint32(&retryTimeout, 1)
428441
return err
429442
}
430-
431-
if err := cn.WithReader(c.context(ctx), c.cmdTimeout(cmd), cmd.readReply); err != nil {
443+
readReplyFunc := cmd.readReply
444+
// Apply unstable RESP3 search module.
445+
if c.opt.Protocol != 2 && c.assertUnstableCommand(cmd) {
446+
readReplyFunc = cmd.readRawReply
447+
}
448+
if err := cn.WithReader(c.context(ctx), c.cmdTimeout(cmd), readReplyFunc); err != nil {
432449
if cmd.readTimeout() == nil {
433450
atomic.StoreUint32(&retryTimeout, 1)
434451
} else {

ring.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ type RingOptions struct {
100100

101101
DisableIndentity bool
102102
IdentitySuffix string
103+
UnstableResp3 bool
103104
}
104105

105106
func (opt *RingOptions) init() {
@@ -168,6 +169,7 @@ func (opt *RingOptions) clientOptions() *Options {
168169

169170
DisableIndentity: opt.DisableIndentity,
170171
IdentitySuffix: opt.IdentitySuffix,
172+
UnstableResp3: opt.UnstableResp3,
171173
}
172174
}
173175

search_commands.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,14 @@ func (cmd *AggregateCmd) Result() (*FTAggregateResult, error) {
638638
return cmd.val, cmd.err
639639
}
640640

641+
func (cmd *AggregateCmd) RawVal() interface{} {
642+
return cmd.rawVal
643+
}
644+
645+
func (cmd *AggregateCmd) RawResult() (interface{}, error) {
646+
return cmd.rawVal, cmd.err
647+
}
648+
641649
func (cmd *AggregateCmd) String() string {
642650
return cmdString(cmd, cmd.val)
643651
}
@@ -1337,6 +1345,13 @@ func (cmd *FTInfoCmd) Val() FTInfoResult {
13371345
return cmd.val
13381346
}
13391347

1348+
func (cmd *FTInfoCmd) RawVal() interface{} {
1349+
return cmd.rawVal
1350+
}
1351+
1352+
func (cmd *FTInfoCmd) RawResult() (interface{}, error) {
1353+
return cmd.rawVal, cmd.err
1354+
}
13401355
func (cmd *FTInfoCmd) readReply(rd *proto.Reader) (err error) {
13411356
n, err := rd.ReadMapLen()
13421357
if err != nil {
@@ -1447,6 +1462,14 @@ func (cmd *FTSpellCheckCmd) Val() []SpellCheckResult {
14471462
return cmd.val
14481463
}
14491464

1465+
func (cmd *FTSpellCheckCmd) RawVal() interface{} {
1466+
return cmd.rawVal
1467+
}
1468+
1469+
func (cmd *FTSpellCheckCmd) RawResult() (interface{}, error) {
1470+
return cmd.rawVal, cmd.err
1471+
}
1472+
14501473
func (cmd *FTSpellCheckCmd) readReply(rd *proto.Reader) (err error) {
14511474
data, err := rd.ReadSlice()
14521475
if err != nil {
@@ -1628,6 +1651,14 @@ func (cmd *FTSearchCmd) Val() FTSearchResult {
16281651
return cmd.val
16291652
}
16301653

1654+
func (cmd *FTSearchCmd) RawVal() interface{} {
1655+
return cmd.rawVal
1656+
}
1657+
1658+
func (cmd *FTSearchCmd) RawResult() (interface{}, error) {
1659+
return cmd.rawVal, cmd.err
1660+
}
1661+
16311662
func (cmd *FTSearchCmd) readReply(rd *proto.Reader) (err error) {
16321663
data, err := rd.ReadSlice()
16331664
if err != nil {
@@ -1904,6 +1935,14 @@ func (cmd *FTSynDumpCmd) Result() ([]FTSynDumpResult, error) {
19041935
return cmd.val, cmd.err
19051936
}
19061937

1938+
func (cmd *FTSynDumpCmd) RawVal() interface{} {
1939+
return cmd.rawVal
1940+
}
1941+
1942+
func (cmd *FTSynDumpCmd) RawResult() (interface{}, error) {
1943+
return cmd.rawVal, cmd.err
1944+
}
1945+
19071946
func (cmd *FTSynDumpCmd) readReply(rd *proto.Reader) error {
19081947
termSynonymPairs, err := rd.ReadSlice()
19091948
if err != nil {

0 commit comments

Comments
 (0)