From 1b8afbebc891223607367836b8f2b3c8f6f1ccbd Mon Sep 17 00:00:00 2001 From: Vladyslav Vildanov <117659936+vladvildanov@users.noreply.github.com> Date: Wed, 31 Jul 2024 11:15:15 +0300 Subject: [PATCH 01/14] Updated module version that points to retracted package version (#3074) * Updated module version that points to retracted package version * Updated testing image to latest --- .github/workflows/build.yml | 2 +- example/del-keys-without-ttl/go.mod | 2 +- example/hll/go.mod | 2 +- example/lua-scripting/go.mod | 2 +- example/otel/go.mod | 6 +++--- example/redis-bloom/go.mod | 2 +- example/scan-struct/go.mod | 2 +- extra/rediscensus/go.mod | 4 ++-- extra/rediscmd/go.mod | 2 +- extra/redisotel/go.mod | 4 ++-- extra/redisprometheus/go.mod | 2 +- version.go | 2 +- 12 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4061bbdff..bef062840 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,7 @@ jobs: services: redis: - image: redis/redis-stack-server:edge + image: redis/redis-stack-server:latest options: >- --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 ports: diff --git a/example/del-keys-without-ttl/go.mod b/example/del-keys-without-ttl/go.mod index 468d0a54f..715454c65 100644 --- a/example/del-keys-without-ttl/go.mod +++ b/example/del-keys-without-ttl/go.mod @@ -5,7 +5,7 @@ go 1.18 replace github.com/redis/go-redis/v9 => ../.. require ( - github.com/redis/go-redis/v9 v9.5.3 + github.com/redis/go-redis/v9 v9.6.1 go.uber.org/zap v1.24.0 ) diff --git a/example/hll/go.mod b/example/hll/go.mod index 0126764ef..f68ff25d5 100644 --- a/example/hll/go.mod +++ b/example/hll/go.mod @@ -4,7 +4,7 @@ go 1.18 replace github.com/redis/go-redis/v9 => ../.. -require github.com/redis/go-redis/v9 v9.5.3 +require github.com/redis/go-redis/v9 v9.6.1 require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect diff --git a/example/lua-scripting/go.mod b/example/lua-scripting/go.mod index 3f4c29d12..176e03d09 100644 --- a/example/lua-scripting/go.mod +++ b/example/lua-scripting/go.mod @@ -4,7 +4,7 @@ go 1.18 replace github.com/redis/go-redis/v9 => ../.. -require github.com/redis/go-redis/v9 v9.5.3 +require github.com/redis/go-redis/v9 v9.6.1 require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect diff --git a/example/otel/go.mod b/example/otel/go.mod index fea4e72a5..2b5030ab6 100644 --- a/example/otel/go.mod +++ b/example/otel/go.mod @@ -9,8 +9,8 @@ replace github.com/redis/go-redis/extra/redisotel/v9 => ../../extra/redisotel replace github.com/redis/go-redis/extra/rediscmd/v9 => ../../extra/rediscmd require ( - github.com/redis/go-redis/extra/redisotel/v9 v9.5.3 - github.com/redis/go-redis/v9 v9.5.3 + github.com/redis/go-redis/extra/redisotel/v9 v9.6.1 + github.com/redis/go-redis/v9 v9.6.1 github.com/uptrace/uptrace-go v1.21.0 go.opentelemetry.io/otel v1.22.0 ) @@ -23,7 +23,7 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect - github.com/redis/go-redis/extra/rediscmd/v9 v9.5.3 // indirect + github.com/redis/go-redis/extra/rediscmd/v9 v9.6.1 // indirect go.opentelemetry.io/contrib/instrumentation/runtime v0.46.1 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect diff --git a/example/redis-bloom/go.mod b/example/redis-bloom/go.mod index 09fb5bed4..d8e9bfffe 100644 --- a/example/redis-bloom/go.mod +++ b/example/redis-bloom/go.mod @@ -4,7 +4,7 @@ go 1.18 replace github.com/redis/go-redis/v9 => ../.. -require github.com/redis/go-redis/v9 v9.5.3 +require github.com/redis/go-redis/v9 v9.6.1 require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect diff --git a/example/scan-struct/go.mod b/example/scan-struct/go.mod index c01e31293..45423ec52 100644 --- a/example/scan-struct/go.mod +++ b/example/scan-struct/go.mod @@ -6,7 +6,7 @@ replace github.com/redis/go-redis/v9 => ../.. require ( github.com/davecgh/go-spew v1.1.1 - github.com/redis/go-redis/v9 v9.5.3 + github.com/redis/go-redis/v9 v9.6.1 ) require ( diff --git a/extra/rediscensus/go.mod b/extra/rediscensus/go.mod index d623cef36..7b99a888e 100644 --- a/extra/rediscensus/go.mod +++ b/extra/rediscensus/go.mod @@ -7,8 +7,8 @@ replace github.com/redis/go-redis/v9 => ../.. replace github.com/redis/go-redis/extra/rediscmd/v9 => ../rediscmd require ( - github.com/redis/go-redis/extra/rediscmd/v9 v9.5.3 - github.com/redis/go-redis/v9 v9.5.3 + github.com/redis/go-redis/extra/rediscmd/v9 v9.6.1 + github.com/redis/go-redis/v9 v9.6.1 go.opencensus.io v0.24.0 ) diff --git a/extra/rediscmd/go.mod b/extra/rediscmd/go.mod index a035c8694..2884faf9a 100644 --- a/extra/rediscmd/go.mod +++ b/extra/rediscmd/go.mod @@ -7,7 +7,7 @@ replace github.com/redis/go-redis/v9 => ../.. require ( github.com/bsm/ginkgo/v2 v2.12.0 github.com/bsm/gomega v1.27.10 - github.com/redis/go-redis/v9 v9.5.3 + github.com/redis/go-redis/v9 v9.6.1 ) require ( diff --git a/extra/redisotel/go.mod b/extra/redisotel/go.mod index 587d3bc3a..12dd414a1 100644 --- a/extra/redisotel/go.mod +++ b/extra/redisotel/go.mod @@ -7,8 +7,8 @@ replace github.com/redis/go-redis/v9 => ../.. replace github.com/redis/go-redis/extra/rediscmd/v9 => ../rediscmd require ( - github.com/redis/go-redis/extra/rediscmd/v9 v9.5.3 - github.com/redis/go-redis/v9 v9.5.3 + github.com/redis/go-redis/extra/rediscmd/v9 v9.6.1 + github.com/redis/go-redis/v9 v9.6.1 go.opentelemetry.io/otel v1.22.0 go.opentelemetry.io/otel/metric v1.22.0 go.opentelemetry.io/otel/sdk v1.22.0 diff --git a/extra/redisprometheus/go.mod b/extra/redisprometheus/go.mod index fcc35b9bd..aedca634a 100644 --- a/extra/redisprometheus/go.mod +++ b/extra/redisprometheus/go.mod @@ -6,7 +6,7 @@ replace github.com/redis/go-redis/v9 => ../.. require ( github.com/prometheus/client_golang v1.14.0 - github.com/redis/go-redis/v9 v9.5.3 + github.com/redis/go-redis/v9 v9.6.1 ) require ( diff --git a/version.go b/version.go index 2ea7df99a..b1234dac3 100644 --- a/version.go +++ b/version.go @@ -2,5 +2,5 @@ package redis // Version is the current release version. func Version() string { - return "9.5.3" + return "9.6.1" } From 3408303c946748805eceb3744c8167ed71fc5c68 Mon Sep 17 00:00:00 2001 From: ofekshenawa Date: Sat, 31 Aug 2024 19:10:42 +0300 Subject: [PATCH 02/14] support raw parsing for problematic Redis Search types --- command.go | 22 ++++++++++++++++------ redis.go | 23 ++++++++++++++++++++--- search_commands.go | 39 +++++++++++++++++++++++++++++++++++++++ search_test.go | 4 ++-- 4 files changed, 77 insertions(+), 11 deletions(-) diff --git a/command.go b/command.go index 9ae97a95a..7b1d6332c 100644 --- a/command.go +++ b/command.go @@ -40,7 +40,7 @@ type Cmder interface { readTimeout() *time.Duration readReply(rd *proto.Reader) error - + readRawReply(rd *proto.Reader) error SetErr(error) Err() error } @@ -122,11 +122,11 @@ func cmdString(cmd Cmder, val interface{}) string { //------------------------------------------------------------------------------ type baseCmd struct { - ctx context.Context - args []interface{} - err error - keyPos int8 - + ctx context.Context + args []interface{} + err error + keyPos int8 + rawVal interface{} _readTimeout *time.Duration } @@ -197,6 +197,11 @@ func (cmd *baseCmd) setReadTimeout(d time.Duration) { cmd._readTimeout = &d } +func (cmd *baseCmd) readRawReply(rd *proto.Reader) (err error) { + cmd.rawVal, err = rd.ReadReply() + return err +} + //------------------------------------------------------------------------------ type Cmd struct { @@ -5550,3 +5555,8 @@ func (cmd *MonitorCmd) Stop() { defer cmd.mu.Unlock() cmd.status = monitorStatusStop } + +type SearchCmd struct { + baseCmd + val interface{} +} diff --git a/redis.go b/redis.go index 527afb677..ba14f1fca 100644 --- a/redis.go +++ b/redis.go @@ -4,7 +4,7 @@ import ( "context" "errors" "fmt" - "net" + "net" // TODO change to import only specific method (Not necesarry in compiling) "sync" "sync/atomic" "time" @@ -412,6 +412,20 @@ func (c *baseClient) process(ctx context.Context, cmd Cmder) error { return lastErr } +func (c *baseClient) isProblematicMethodsOfSearchResp3(cmd Cmder) bool { + if c.opt.Protocol != 3 { + return false + } + + switch cmd.(type) { + case *AggregateCmd, *FTInfoCmd, *FTSpellCheckCmd, *FTSearchCmd, *FTSynDumpCmd: + fmt.Println("Some RESP3 results for Redis Query Engine responses may change. Refer to the readme for guidance") + return true + default: + return false + } +} + func (c *baseClient) _process(ctx context.Context, cmd Cmder, attempt int) (bool, error) { if attempt > 0 { if err := internal.Sleep(ctx, c.retryBackoff(attempt)); err != nil { @@ -427,8 +441,11 @@ func (c *baseClient) _process(ctx context.Context, cmd Cmder, attempt int) (bool atomic.StoreUint32(&retryTimeout, 1) return err } - - if err := cn.WithReader(c.context(ctx), c.cmdTimeout(cmd), cmd.readReply); err != nil { + readReplyFunc := cmd.readReply + if c.isProblematicMethodsOfSearchResp3(cmd) { + readReplyFunc = cmd.readRawReply + } + if err := cn.WithReader(c.context(ctx), c.cmdTimeout(cmd), readReplyFunc); err != nil { if cmd.readTimeout() == nil { atomic.StoreUint32(&retryTimeout, 1) } else { diff --git a/search_commands.go b/search_commands.go index f5118c77e..1a8a4cfef 100644 --- a/search_commands.go +++ b/search_commands.go @@ -638,6 +638,14 @@ func (cmd *AggregateCmd) Result() (*FTAggregateResult, error) { return cmd.val, cmd.err } +func (cmd *AggregateCmd) RawVal() interface{} { + return cmd.rawVal +} + +func (cmd *AggregateCmd) RawResult() (interface{}, error) { + return cmd.rawVal, cmd.err +} + func (cmd *AggregateCmd) String() string { return cmdString(cmd, cmd.val) } @@ -1337,6 +1345,13 @@ func (cmd *FTInfoCmd) Val() FTInfoResult { return cmd.val } +func (cmd *FTInfoCmd) RawVal() interface{} { + return cmd.rawVal +} + +func (cmd *FTInfoCmd) RawResult() (interface{}, error) { + return cmd.rawVal, cmd.err +} func (cmd *FTInfoCmd) readReply(rd *proto.Reader) (err error) { n, err := rd.ReadMapLen() if err != nil { @@ -1447,6 +1462,14 @@ func (cmd *FTSpellCheckCmd) Val() []SpellCheckResult { return cmd.val } +func (cmd *FTSpellCheckCmd) RawVal() interface{} { + return cmd.rawVal +} + +func (cmd *FTSpellCheckCmd) RawResult() (interface{}, error) { + return cmd.rawVal, cmd.err +} + func (cmd *FTSpellCheckCmd) readReply(rd *proto.Reader) (err error) { data, err := rd.ReadSlice() if err != nil { @@ -1628,6 +1651,14 @@ func (cmd *FTSearchCmd) Val() FTSearchResult { return cmd.val } +func (cmd *FTSearchCmd) RawVal() interface{} { + return cmd.rawVal +} + +func (cmd *FTSearchCmd) RawResult() (interface{}, error) { + return cmd.rawVal, cmd.err +} + func (cmd *FTSearchCmd) readReply(rd *proto.Reader) (err error) { data, err := rd.ReadSlice() if err != nil { @@ -1904,6 +1935,14 @@ func (cmd *FTSynDumpCmd) Result() ([]FTSynDumpResult, error) { return cmd.val, cmd.err } +func (cmd *FTSynDumpCmd) RawVal() interface{} { + return cmd.rawVal +} + +func (cmd *FTSynDumpCmd) RawResult() (interface{}, error) { + return cmd.rawVal, cmd.err +} + func (cmd *FTSynDumpCmd) readReply(rd *proto.Reader) error { termSynonymPairs, err := rd.ReadSlice() if err != nil { diff --git a/search_test.go b/search_test.go index 0e1a473b8..b326b0d77 100644 --- a/search_test.go +++ b/search_test.go @@ -22,12 +22,12 @@ func WaitForIndexing(c *redis.Client, index string) { } } -var _ = Describe("RediSearch commands", Label("search"), func() { +var _ = Describe("RediSearch commands Resp 2", Label("search"), func() { ctx := context.TODO() var client *redis.Client BeforeEach(func() { - client = redis.NewClient(&redis.Options{Addr: ":6379", Protocol: 2}) + client = redis.NewClient(&redis.Options{Addr: ":6379", Protocol: 3}) Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) }) From d30695a78b1bf0080c7db18515509c4ce3776bdb Mon Sep 17 00:00:00 2001 From: ofekshenawa Date: Sat, 31 Aug 2024 19:28:50 +0300 Subject: [PATCH 03/14] Add UnstableResp3SearchModule to client options --- options.go | 3 +++ redis.go | 5 +++-- ring.go | 10 ++++++---- sentinel.go | 15 +++++++++------ universal.go | 15 +++++++++------ 5 files changed, 30 insertions(+), 18 deletions(-) diff --git a/options.go b/options.go index 6ed693a0b..f7fd4c16c 100644 --- a/options.go +++ b/options.go @@ -153,6 +153,9 @@ type Options struct { // Add suffix to client name. Default is empty. IdentitySuffix string + + // Enable Unstable mode for Redis Search module with RESP3. + UnstableResp3SearchModule bool } func (opt *Options) init() { diff --git a/redis.go b/redis.go index ba14f1fca..301852839 100644 --- a/redis.go +++ b/redis.go @@ -4,7 +4,7 @@ import ( "context" "errors" "fmt" - "net" // TODO change to import only specific method (Not necesarry in compiling) + "net" "sync" "sync/atomic" "time" @@ -442,7 +442,8 @@ func (c *baseClient) _process(ctx context.Context, cmd Cmder, attempt int) (bool return err } readReplyFunc := cmd.readReply - if c.isProblematicMethodsOfSearchResp3(cmd) { + // Apply unstable RESP3 search module. + if c.opt.UnstableResp3SearchModule && c.isProblematicMethodsOfSearchResp3(cmd) { readReplyFunc = cmd.readRawReply } if err := cn.WithReader(c.context(ctx), c.cmdTimeout(cmd), readReplyFunc); err != nil { diff --git a/ring.go b/ring.go index 4ae00542b..5768e90b3 100644 --- a/ring.go +++ b/ring.go @@ -98,8 +98,9 @@ type RingOptions struct { TLSConfig *tls.Config Limiter Limiter - DisableIndentity bool - IdentitySuffix string + DisableIndentity bool + IdentitySuffix string + UnstableResp3SearchModule bool } func (opt *RingOptions) init() { @@ -166,8 +167,9 @@ func (opt *RingOptions) clientOptions() *Options { TLSConfig: opt.TLSConfig, Limiter: opt.Limiter, - DisableIndentity: opt.DisableIndentity, - IdentitySuffix: opt.IdentitySuffix, + DisableIndentity: opt.DisableIndentity, + IdentitySuffix: opt.IdentitySuffix, + UnstableResp3SearchModule: opt.UnstableResp3SearchModule, } } diff --git a/sentinel.go b/sentinel.go index 188f88494..925d76065 100644 --- a/sentinel.go +++ b/sentinel.go @@ -80,8 +80,9 @@ type FailoverOptions struct { TLSConfig *tls.Config - DisableIndentity bool - IdentitySuffix string + DisableIndentity bool + IdentitySuffix string + UnstableResp3SearchModule bool } func (opt *FailoverOptions) clientOptions() *Options { @@ -117,8 +118,9 @@ func (opt *FailoverOptions) clientOptions() *Options { TLSConfig: opt.TLSConfig, - DisableIndentity: opt.DisableIndentity, - IdentitySuffix: opt.IdentitySuffix, + DisableIndentity: opt.DisableIndentity, + IdentitySuffix: opt.IdentitySuffix, + UnstableResp3SearchModule: opt.UnstableResp3SearchModule, } } @@ -154,8 +156,9 @@ func (opt *FailoverOptions) sentinelOptions(addr string) *Options { TLSConfig: opt.TLSConfig, - DisableIndentity: opt.DisableIndentity, - IdentitySuffix: opt.IdentitySuffix, + DisableIndentity: opt.DisableIndentity, + IdentitySuffix: opt.IdentitySuffix, + UnstableResp3SearchModule: opt.UnstableResp3SearchModule, } } diff --git a/universal.go b/universal.go index 275bef3d6..eae365e5d 100644 --- a/universal.go +++ b/universal.go @@ -66,8 +66,9 @@ type UniversalOptions struct { MasterName string - DisableIndentity bool - IdentitySuffix string + DisableIndentity bool + IdentitySuffix string + UnstableResp3SearchModule bool } // Cluster returns cluster options created from the universal options. @@ -158,8 +159,9 @@ func (o *UniversalOptions) Failover() *FailoverOptions { TLSConfig: o.TLSConfig, - DisableIndentity: o.DisableIndentity, - IdentitySuffix: o.IdentitySuffix, + DisableIndentity: o.DisableIndentity, + IdentitySuffix: o.IdentitySuffix, + UnstableResp3SearchModule: o.UnstableResp3SearchModule, } } @@ -201,8 +203,9 @@ func (o *UniversalOptions) Simple() *Options { TLSConfig: o.TLSConfig, - DisableIndentity: o.DisableIndentity, - IdentitySuffix: o.IdentitySuffix, + DisableIndentity: o.DisableIndentity, + IdentitySuffix: o.IdentitySuffix, + UnstableResp3SearchModule: o.UnstableResp3SearchModule, } } From abaa1d9a7de3e47ee175916f732b22b41eea6a02 Mon Sep 17 00:00:00 2001 From: ofekshenawa Date: Sat, 31 Aug 2024 21:02:38 +0300 Subject: [PATCH 04/14] Add tests for Resp3 Search unstable mode --- command.go | 5 -- search_test.go | 177 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 176 insertions(+), 6 deletions(-) diff --git a/command.go b/command.go index 7b1d6332c..4ced2979d 100644 --- a/command.go +++ b/command.go @@ -5555,8 +5555,3 @@ func (cmd *MonitorCmd) Stop() { defer cmd.mu.Unlock() cmd.status = monitorStatusStop } - -type SearchCmd struct { - baseCmd - val interface{} -} diff --git a/search_test.go b/search_test.go index b326b0d77..1d24e7e99 100644 --- a/search_test.go +++ b/search_test.go @@ -18,6 +18,8 @@ func WaitForIndexing(c *redis.Client, index string) { return } time.Sleep(100 * time.Millisecond) + } else { + return } } } @@ -27,7 +29,7 @@ var _ = Describe("RediSearch commands Resp 2", Label("search"), func() { var client *redis.Client BeforeEach(func() { - client = redis.NewClient(&redis.Options{Addr: ":6379", Protocol: 3}) + client = redis.NewClient(&redis.Options{Addr: ":6379", Protocol: 2}) Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) }) @@ -1415,3 +1417,176 @@ func _assert_geosearch_result(result *redis.FTSearchResult, expectedDocIDs []str // Expect(results0["id"]).To(BeEquivalentTo("a")) // Expect(results0["extra_attributes"].(map[interface{}]interface{})["__v_score"]).To(BeEquivalentTo("0")) // }) + +var _ = Describe("RediSearch commands Resp 3", Label("search"), func() { + ctx := context.TODO() + var client *redis.Client + var client2 *redis.Client + + BeforeEach(func() { + client = redis.NewClient(&redis.Options{Addr: ":6379", Protocol: 3, UnstableResp3SearchModule: true}) + client2 = redis.NewClient(&redis.Options{Addr: ":6379", Protocol: 3}) + Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + Expect(client.Close()).NotTo(HaveOccurred()) + }) + + It("should handle FTAggregate with Unstable RESP3 Search Module and without stability", Label("search", "ftcreate", "ftaggregate"), func() { + text1 := &redis.FieldSchema{FieldName: "PrimaryKey", FieldType: redis.SearchFieldTypeText, Sortable: true} + num1 := &redis.FieldSchema{FieldName: "CreatedDateTimeUTC", FieldType: redis.SearchFieldTypeNumeric, Sortable: true} + val, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{}, text1, num1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(BeEquivalentTo("OK")) + WaitForIndexing(client, "idx1") + + client.HSet(ctx, "doc1", "PrimaryKey", "9::362330", "CreatedDateTimeUTC", "637387878524969984") + client.HSet(ctx, "doc2", "PrimaryKey", "9::362329", "CreatedDateTimeUTC", "637387875859270016") + + options := &redis.FTAggregateOptions{Apply: []redis.FTAggregateApply{{Field: "@CreatedDateTimeUTC * 10", As: "CreatedDateTimeUTC"}}} + res, err := client.FTAggregateWithArgs(ctx, "idx1", "*", options).RawResult() + rawVal := client.FTAggregateWithArgs(ctx, "idx1", "*", options).RawVal() + + Expect(err).NotTo(HaveOccurred()) + Expect(rawVal).To(BeEquivalentTo(res)) + results := res.(map[interface{}]interface{})["results"].([]interface{}) + Expect(results[0].(map[interface{}]interface{})["extra_attributes"].(map[interface{}]interface{})["CreatedDateTimeUTC"]). + To(Or(BeEquivalentTo("6373878785249699840"), BeEquivalentTo("6373878758592700416"))) + Expect(results[1].(map[interface{}]interface{})["extra_attributes"].(map[interface{}]interface{})["CreatedDateTimeUTC"]). + To(Or(BeEquivalentTo("6373878785249699840"), BeEquivalentTo("6373878758592700416"))) + + // Test with UnstableResp3SearchModule false + options = &redis.FTAggregateOptions{Apply: []redis.FTAggregateApply{{Field: "@CreatedDateTimeUTC * 10", As: "CreatedDateTimeUTC"}}} + rawRes, _ := client2.FTAggregateWithArgs(ctx, "idx1", "*", options).RawResult() + rawVal = client2.FTAggregateWithArgs(ctx, "idx1", "*", options).RawVal() + Expect(rawRes).To(BeNil()) + Expect(rawVal).To(BeNil()) + + }) + + It("should handle FTInfo with Unstable RESP3 Search Module and without stability", Label("search", "ftcreate", "ftinfo"), func() { + val, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{}, &redis.FieldSchema{FieldName: "txt", FieldType: redis.SearchFieldTypeText, Sortable: true, NoStem: true}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(BeEquivalentTo("OK")) + WaitForIndexing(client, "idx1") + + resInfo, err := client.FTInfo(ctx, "idx1").RawResult() + Expect(err).NotTo(HaveOccurred()) + attributes := resInfo.(map[interface{}]interface{})["attributes"].([]interface{}) + flags := attributes[0].(map[interface{}]interface{})["flags"].([]interface{}) + Expect(flags).To(ConsistOf("SORTABLE", "NOSTEM")) + + valInfo := client.FTInfo(ctx, "idx1").RawVal() + attributes = valInfo.(map[interface{}]interface{})["attributes"].([]interface{}) + flags = attributes[0].(map[interface{}]interface{})["flags"].([]interface{}) + Expect(flags).To(ConsistOf("SORTABLE", "NOSTEM")) + + // Test with UnstableResp3SearchModule false + rawResInfo, _ := client2.FTInfo(ctx, "idx1").RawResult() + rawValInfo := client2.FTInfo(ctx, "idx1").RawVal() + Expect(rawResInfo).To(BeNil()) + Expect(rawValInfo).To(BeNil()) + }) + + It("should handle FTSpellCheck with Unstable RESP3 Search Module and without stability", Label("search", "ftcreate", "ftspellcheck"), func() { + text1 := &redis.FieldSchema{FieldName: "f1", FieldType: redis.SearchFieldTypeText} + text2 := &redis.FieldSchema{FieldName: "f2", FieldType: redis.SearchFieldTypeText} + val, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{}, text1, text2).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(BeEquivalentTo("OK")) + WaitForIndexing(client, "idx1") + + client.HSet(ctx, "doc1", "f1", "some valid content", "f2", "this is sample text") + client.HSet(ctx, "doc2", "f1", "very important", "f2", "lorem ipsum") + + resSpellCheck, err := client.FTSpellCheck(ctx, "idx1", "impornant").RawResult() + valSpellCheck := client.FTSpellCheck(ctx, "idx1", "impornant").RawVal() + Expect(err).NotTo(HaveOccurred()) + Expect(valSpellCheck).To(BeEquivalentTo(resSpellCheck)) + results := resSpellCheck.(map[interface{}]interface{})["results"].(map[interface{}]interface{}) + Expect(results["impornant"].([]interface{})[0].(map[interface{}]interface{})["important"]).To(BeEquivalentTo(0.5)) + + // Test with UnstableResp3SearchModule false + rawResSpellCheck, _ := client2.FTSpellCheck(ctx, "idx1", "impornant").RawResult() + rawValSpellCheck := client2.FTSpellCheck(ctx, "idx1", "impornant").RawVal() + Expect(rawResSpellCheck).To(BeNil()) + Expect(rawValSpellCheck).To(BeNil()) + }) + + It("should handle FTSearch with Unstable RESP3 Search Module and without stability", Label("search", "ftcreate", "ftsearch"), func() { + val, err := client.FTCreate(ctx, "txt", &redis.FTCreateOptions{StopWords: []interface{}{"foo", "bar", "baz"}}, &redis.FieldSchema{FieldName: "txt", FieldType: redis.SearchFieldTypeText}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(BeEquivalentTo("OK")) + WaitForIndexing(client, "txt") + client.HSet(ctx, "doc1", "txt", "foo baz") + client.HSet(ctx, "doc2", "txt", "hello world") + res1, err := client.FTSearchWithArgs(ctx, "txt", "foo bar", &redis.FTSearchOptions{NoContent: true}).RawResult() + val1 := client.FTSearchWithArgs(ctx, "txt", "foo bar", &redis.FTSearchOptions{NoContent: true}).RawVal() + Expect(err).NotTo(HaveOccurred()) + Expect(val1).To(BeEquivalentTo(res1)) + totalResults := res1.(map[interface{}]interface{})["total_results"] + Expect(totalResults).To(BeEquivalentTo(int64(0))) + res2, err := client.FTSearchWithArgs(ctx, "txt", "foo bar hello world", &redis.FTSearchOptions{NoContent: true}).RawResult() + Expect(err).NotTo(HaveOccurred()) + totalResults2 := res2.(map[interface{}]interface{})["total_results"] + Expect(totalResults2).To(BeEquivalentTo(int64(1))) + + // Test with UnstableResp3SearchModule false + rawRes2, _ := client2.FTSearchWithArgs(ctx, "txt", "foo bar hello world", &redis.FTSearchOptions{NoContent: true}).RawResult() + rawVal2 := client2.FTSearchWithArgs(ctx, "txt", "foo bar hello world", &redis.FTSearchOptions{NoContent: true}).RawVal() + Expect(rawRes2).To(BeNil()) + Expect(rawVal2).To(BeNil()) + + }) + It("should handle FTSynDump with Unstable RESP3 Search Module and without stability", Label("search", "ftsyndump"), func() { + text1 := &redis.FieldSchema{FieldName: "title", FieldType: redis.SearchFieldTypeText} + text2 := &redis.FieldSchema{FieldName: "body", FieldType: redis.SearchFieldTypeText} + val, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{OnHash: true}, text1, text2).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(BeEquivalentTo("OK")) + WaitForIndexing(client, "idx1") + + resSynUpdate, err := client.FTSynUpdate(ctx, "idx1", "id1", []interface{}{"boy", "child", "offspring"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(resSynUpdate).To(BeEquivalentTo("OK")) + + resSynUpdate, err = client.FTSynUpdate(ctx, "idx1", "id1", []interface{}{"baby", "child"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(resSynUpdate).To(BeEquivalentTo("OK")) + + resSynUpdate, err = client.FTSynUpdate(ctx, "idx1", "id1", []interface{}{"tree", "wood"}).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(resSynUpdate).To(BeEquivalentTo("OK")) + + resSynDump, err := client.FTSynDump(ctx, "idx1").RawResult() + valSynDump := client.FTSynDump(ctx, "idx1").RawVal() + Expect(err).NotTo(HaveOccurred()) + Expect(valSynDump).To(BeEquivalentTo(resSynDump)) + Expect(resSynDump.(map[interface{}]interface{})["baby"]).To(BeEquivalentTo([]interface{}{"id1"})) + + // Test with UnstableResp3SearchModule false + rawResSynDump, _ := client2.FTSynDump(ctx, "idx1").RawResult() + rawValSynDump := client2.FTSynDump(ctx, "idx1").RawVal() + Expect(rawResSynDump).To(BeNil()) + Expect(rawValSynDump).To(BeNil()) + }) + + It("should test not affected Resp 3 Search method - FTExplain", Label("search", "ftexplain"), func() { + text1 := &redis.FieldSchema{FieldName: "f1", FieldType: redis.SearchFieldTypeText} + text2 := &redis.FieldSchema{FieldName: "f2", FieldType: redis.SearchFieldTypeText} + text3 := &redis.FieldSchema{FieldName: "f3", FieldType: redis.SearchFieldTypeText} + val, err := client.FTCreate(ctx, "txt", &redis.FTCreateOptions{}, text1, text2, text3).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(val).To(BeEquivalentTo("OK")) + WaitForIndexing(client, "txt") + res1, err := client.FTExplain(ctx, "txt", "@f3:f3_val @f2:f2_val @f1:f1_val").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(res1).ToNot(BeEmpty()) + + // Test with UnstableResp3SearchModule false + res2, err := client2.FTExplain(ctx, "txt", "@f3:f3_val @f2:f2_val @f1:f1_val").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(res2).ToNot(BeEmpty()) + }) +}) From 4072a8038978f1ea4f91e8d1a3b0c18077478cab Mon Sep 17 00:00:00 2001 From: ofekshenawa Date: Sat, 31 Aug 2024 21:08:34 +0300 Subject: [PATCH 05/14] Add tests for Resp3 Search unstable mode --- redis.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/redis.go b/redis.go index 301852839..56d22fc77 100644 --- a/redis.go +++ b/redis.go @@ -412,14 +412,14 @@ func (c *baseClient) process(ctx context.Context, cmd Cmder) error { return lastErr } -func (c *baseClient) isProblematicMethodsOfSearchResp3(cmd Cmder) bool { +func (c *baseClient) isProblematicMethodsOfSearchResp3(ctx context.Context, cmd Cmder) bool { if c.opt.Protocol != 3 { return false } switch cmd.(type) { case *AggregateCmd, *FTInfoCmd, *FTSpellCheckCmd, *FTSearchCmd, *FTSynDumpCmd: - fmt.Println("Some RESP3 results for Redis Query Engine responses may change. Refer to the readme for guidance") + internal.Logger.Printf(ctx, "Some RESP3 results for Redis Query Engine responses may change. Refer to the readme for guidance") return true default: return false @@ -443,7 +443,7 @@ func (c *baseClient) _process(ctx context.Context, cmd Cmder, attempt int) (bool } readReplyFunc := cmd.readReply // Apply unstable RESP3 search module. - if c.opt.UnstableResp3SearchModule && c.isProblematicMethodsOfSearchResp3(cmd) { + if c.opt.UnstableResp3SearchModule && c.isProblematicMethodsOfSearchResp3(ctx, cmd) { readReplyFunc = cmd.readRawReply } if err := cn.WithReader(c.context(ctx), c.cmdTimeout(cmd), readReplyFunc); err != nil { From 8246f1d820b752a647941f24e6242f93160ae641 Mon Sep 17 00:00:00 2001 From: ofekshenawa Date: Sat, 31 Aug 2024 21:41:21 +0300 Subject: [PATCH 06/14] Add readme note --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index e7df5dfd6..e919f1d2f 100644 --- a/README.md +++ b/README.md @@ -182,6 +182,9 @@ rdb := redis.NewClient(&redis.Options{ }) ``` +#### Unstable RESP3 Structures for RediSearch Commands +When connecting with Redis using RESP3 protocol, it's important to note that some response structures aren't final yet. This is the case for more complex structures in FT.SEARCH, FT.AGGREGATE, FT.Info, FT.SpellCheck and FT.SynDump. We recommend using RESP2 when using these commands, but we plan to stabilize the RESP3-based APIs in the coming versions. You can find more guidance in the upcoming release notes. + ## Contributing Please see [out contributing guidelines](CONTRIBUTING.md) to help us improve this library! From 8f3373bfba02933a0e750a3aefa632aef2cdbe62 Mon Sep 17 00:00:00 2001 From: ofekshenawa Date: Sat, 31 Aug 2024 21:59:34 +0300 Subject: [PATCH 07/14] Add words to spellcheck --- .github/wordlist.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/wordlist.txt b/.github/wordlist.txt index dceddff46..c200c60b4 100644 --- a/.github/wordlist.txt +++ b/.github/wordlist.txt @@ -1,4 +1,5 @@ ACLs +APIs autoload autoloader autoloading @@ -46,9 +47,11 @@ runtime SHA sharding SETNAME +SpellCheck SSL struct stunnel +SynDump TCP TLS uri From ca4e352011c50520489dccc72f2a324a8817377c Mon Sep 17 00:00:00 2001 From: ofekshenawa Date: Mon, 2 Sep 2024 11:46:38 +0300 Subject: [PATCH 08/14] Add UnstableResp3SearchModule check to assertStableCommand --- redis.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/redis.go b/redis.go index 56d22fc77..2bcd77ee8 100644 --- a/redis.go +++ b/redis.go @@ -412,18 +412,18 @@ func (c *baseClient) process(ctx context.Context, cmd Cmder) error { return lastErr } -func (c *baseClient) isProblematicMethodsOfSearchResp3(ctx context.Context, cmd Cmder) bool { - if c.opt.Protocol != 3 { - return false +func (c *baseClient) assertStableCommand(ctx context.Context, cmd Cmder) bool { + if c.opt.Protocol != 2 && c.opt.UnstableResp3SearchModule { + switch cmd.(type) { + case *AggregateCmd, *FTInfoCmd, *FTSpellCheckCmd, *FTSearchCmd, *FTSynDumpCmd: + internal.Logger.Printf(ctx, "Some RESP3 results for Redis Query Engine responses may change. Refer to the readme for guidance") + return true + default: + return false + } } + return false - switch cmd.(type) { - case *AggregateCmd, *FTInfoCmd, *FTSpellCheckCmd, *FTSearchCmd, *FTSynDumpCmd: - internal.Logger.Printf(ctx, "Some RESP3 results for Redis Query Engine responses may change. Refer to the readme for guidance") - return true - default: - return false - } } func (c *baseClient) _process(ctx context.Context, cmd Cmder, attempt int) (bool, error) { @@ -443,7 +443,7 @@ func (c *baseClient) _process(ctx context.Context, cmd Cmder, attempt int) (bool } readReplyFunc := cmd.readReply // Apply unstable RESP3 search module. - if c.opt.UnstableResp3SearchModule && c.isProblematicMethodsOfSearchResp3(ctx, cmd) { + if c.assertStableCommand(ctx, cmd) { readReplyFunc = cmd.readRawReply } if err := cn.WithReader(c.context(ctx), c.cmdTimeout(cmd), readReplyFunc); err != nil { From 5b0bb85e1b21aa93c6c74541a7cd01cf8944652a Mon Sep 17 00:00:00 2001 From: ofekshenawa Date: Mon, 2 Sep 2024 12:36:41 +0300 Subject: [PATCH 09/14] Fix assertStableCommand logic --- go.mod | 2 +- redis.go | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index bd13d7453..c1d9037ac 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,6 @@ require ( ) retract ( - v9.5.3 // This version was accidentally released. Please use version 9.6.0 instead. v9.5.4 // This version was accidentally released. Please use version 9.6.0 instead. + v9.5.3 // This version was accidentally released. Please use version 9.6.0 instead. ) diff --git a/redis.go b/redis.go index 2bcd77ee8..3de9db2be 100644 --- a/redis.go +++ b/redis.go @@ -412,18 +412,17 @@ func (c *baseClient) process(ctx context.Context, cmd Cmder) error { return lastErr } -func (c *baseClient) assertStableCommand(ctx context.Context, cmd Cmder) bool { - if c.opt.Protocol != 2 && c.opt.UnstableResp3SearchModule { - switch cmd.(type) { - case *AggregateCmd, *FTInfoCmd, *FTSpellCheckCmd, *FTSearchCmd, *FTSynDumpCmd: - internal.Logger.Printf(ctx, "Some RESP3 results for Redis Query Engine responses may change. Refer to the readme for guidance") +func (c *baseClient) assertStableCommand(cmd Cmder) bool { + switch cmd.(type) { + case *AggregateCmd, *FTInfoCmd, *FTSpellCheckCmd, *FTSearchCmd, *FTSynDumpCmd: + if c.opt.UnstableResp3SearchModule { return true - default: - return false + } else { + panic("Some RESP3 results for Redis Query Engine responses may change. Refer to the readme for guidance") } + default: + return false } - return false - } func (c *baseClient) _process(ctx context.Context, cmd Cmder, attempt int) (bool, error) { @@ -443,7 +442,7 @@ func (c *baseClient) _process(ctx context.Context, cmd Cmder, attempt int) (bool } readReplyFunc := cmd.readReply // Apply unstable RESP3 search module. - if c.assertStableCommand(ctx, cmd) { + if c.opt.Protocol != 2 && c.assertStableCommand(cmd) { readReplyFunc = cmd.readRawReply } if err := cn.WithReader(c.context(ctx), c.cmdTimeout(cmd), readReplyFunc); err != nil { From e7b8c9772343d75db82c7a9428f28986461e09aa Mon Sep 17 00:00:00 2001 From: ofekshenawa Date: Mon, 2 Sep 2024 12:40:56 +0300 Subject: [PATCH 10/14] remove go.mod changes --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index c1d9037ac..bd13d7453 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,6 @@ require ( ) retract ( - v9.5.4 // This version was accidentally released. Please use version 9.6.0 instead. v9.5.3 // This version was accidentally released. Please use version 9.6.0 instead. + v9.5.4 // This version was accidentally released. Please use version 9.6.0 instead. ) From 8ef6321d221b03631fafb4d215d9c82f313364f3 Mon Sep 17 00:00:00 2001 From: ofekshenawa Date: Mon, 2 Sep 2024 12:50:05 +0300 Subject: [PATCH 11/14] Check panic occur on tests --- search_test.go | 61 +++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/search_test.go b/search_test.go index 1d24e7e99..b4617a54f 100644 --- a/search_test.go +++ b/search_test.go @@ -1457,11 +1457,13 @@ var _ = Describe("RediSearch commands Resp 3", Label("search"), func() { To(Or(BeEquivalentTo("6373878785249699840"), BeEquivalentTo("6373878758592700416"))) // Test with UnstableResp3SearchModule false - options = &redis.FTAggregateOptions{Apply: []redis.FTAggregateApply{{Field: "@CreatedDateTimeUTC * 10", As: "CreatedDateTimeUTC"}}} - rawRes, _ := client2.FTAggregateWithArgs(ctx, "idx1", "*", options).RawResult() - rawVal = client2.FTAggregateWithArgs(ctx, "idx1", "*", options).RawVal() - Expect(rawRes).To(BeNil()) - Expect(rawVal).To(BeNil()) + Expect(func() { + options = &redis.FTAggregateOptions{Apply: []redis.FTAggregateApply{{Field: "@CreatedDateTimeUTC * 10", As: "CreatedDateTimeUTC"}}} + rawRes, _ := client2.FTAggregateWithArgs(ctx, "idx1", "*", options).RawResult() + rawVal = client2.FTAggregateWithArgs(ctx, "idx1", "*", options).RawVal() + Expect(rawRes).To(BeNil()) + Expect(rawVal).To(BeNil()) + }).Should(Panic()) }) @@ -1483,10 +1485,12 @@ var _ = Describe("RediSearch commands Resp 3", Label("search"), func() { Expect(flags).To(ConsistOf("SORTABLE", "NOSTEM")) // Test with UnstableResp3SearchModule false - rawResInfo, _ := client2.FTInfo(ctx, "idx1").RawResult() - rawValInfo := client2.FTInfo(ctx, "idx1").RawVal() - Expect(rawResInfo).To(BeNil()) - Expect(rawValInfo).To(BeNil()) + Expect(func() { + rawResInfo, _ := client2.FTInfo(ctx, "idx1").RawResult() + rawValInfo := client2.FTInfo(ctx, "idx1").RawVal() + Expect(rawResInfo).To(BeNil()) + Expect(rawValInfo).To(BeNil()) + }).Should(Panic()) }) It("should handle FTSpellCheck with Unstable RESP3 Search Module and without stability", Label("search", "ftcreate", "ftspellcheck"), func() { @@ -1508,10 +1512,12 @@ var _ = Describe("RediSearch commands Resp 3", Label("search"), func() { Expect(results["impornant"].([]interface{})[0].(map[interface{}]interface{})["important"]).To(BeEquivalentTo(0.5)) // Test with UnstableResp3SearchModule false - rawResSpellCheck, _ := client2.FTSpellCheck(ctx, "idx1", "impornant").RawResult() - rawValSpellCheck := client2.FTSpellCheck(ctx, "idx1", "impornant").RawVal() - Expect(rawResSpellCheck).To(BeNil()) - Expect(rawValSpellCheck).To(BeNil()) + Expect(func() { + rawResSpellCheck, _ := client2.FTSpellCheck(ctx, "idx1", "impornant").RawResult() + rawValSpellCheck := client2.FTSpellCheck(ctx, "idx1", "impornant").RawVal() + Expect(rawResSpellCheck).To(BeNil()) + Expect(rawValSpellCheck).To(BeNil()) + }).Should(Panic()) }) It("should handle FTSearch with Unstable RESP3 Search Module and without stability", Label("search", "ftcreate", "ftsearch"), func() { @@ -1533,11 +1539,12 @@ var _ = Describe("RediSearch commands Resp 3", Label("search"), func() { Expect(totalResults2).To(BeEquivalentTo(int64(1))) // Test with UnstableResp3SearchModule false - rawRes2, _ := client2.FTSearchWithArgs(ctx, "txt", "foo bar hello world", &redis.FTSearchOptions{NoContent: true}).RawResult() - rawVal2 := client2.FTSearchWithArgs(ctx, "txt", "foo bar hello world", &redis.FTSearchOptions{NoContent: true}).RawVal() - Expect(rawRes2).To(BeNil()) - Expect(rawVal2).To(BeNil()) - + Expect(func() { + rawRes2, _ := client2.FTSearchWithArgs(ctx, "txt", "foo bar hello world", &redis.FTSearchOptions{NoContent: true}).RawResult() + rawVal2 := client2.FTSearchWithArgs(ctx, "txt", "foo bar hello world", &redis.FTSearchOptions{NoContent: true}).RawVal() + Expect(rawRes2).To(BeNil()) + Expect(rawVal2).To(BeNil()) + }).Should(Panic()) }) It("should handle FTSynDump with Unstable RESP3 Search Module and without stability", Label("search", "ftsyndump"), func() { text1 := &redis.FieldSchema{FieldName: "title", FieldType: redis.SearchFieldTypeText} @@ -1566,10 +1573,12 @@ var _ = Describe("RediSearch commands Resp 3", Label("search"), func() { Expect(resSynDump.(map[interface{}]interface{})["baby"]).To(BeEquivalentTo([]interface{}{"id1"})) // Test with UnstableResp3SearchModule false - rawResSynDump, _ := client2.FTSynDump(ctx, "idx1").RawResult() - rawValSynDump := client2.FTSynDump(ctx, "idx1").RawVal() - Expect(rawResSynDump).To(BeNil()) - Expect(rawValSynDump).To(BeNil()) + Expect(func() { + rawResSynDump, _ := client2.FTSynDump(ctx, "idx1").RawResult() + rawValSynDump := client2.FTSynDump(ctx, "idx1").RawVal() + Expect(rawResSynDump).To(BeNil()) + Expect(rawValSynDump).To(BeNil()) + }).Should(Panic()) }) It("should test not affected Resp 3 Search method - FTExplain", Label("search", "ftexplain"), func() { @@ -1585,8 +1594,10 @@ var _ = Describe("RediSearch commands Resp 3", Label("search"), func() { Expect(res1).ToNot(BeEmpty()) // Test with UnstableResp3SearchModule false - res2, err := client2.FTExplain(ctx, "txt", "@f3:f3_val @f2:f2_val @f1:f1_val").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(res2).ToNot(BeEmpty()) + Expect(func() { + res2, err := client2.FTExplain(ctx, "txt", "@f3:f3_val @f2:f2_val @f1:f1_val").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(res2).ToNot(BeEmpty()) + }).ShouldNot(Panic()) }) }) From 7b5661819b6f5a9bcb861336506a6a925cad432f Mon Sep 17 00:00:00 2001 From: ofekshenawa Date: Mon, 2 Sep 2024 14:16:43 +0300 Subject: [PATCH 12/14] rename method --- redis.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/redis.go b/redis.go index 3de9db2be..231c2c3e4 100644 --- a/redis.go +++ b/redis.go @@ -412,7 +412,7 @@ func (c *baseClient) process(ctx context.Context, cmd Cmder) error { return lastErr } -func (c *baseClient) assertStableCommand(cmd Cmder) bool { +func (c *baseClient) assertUnstableCommand(cmd Cmder) bool { switch cmd.(type) { case *AggregateCmd, *FTInfoCmd, *FTSpellCheckCmd, *FTSearchCmd, *FTSynDumpCmd: if c.opt.UnstableResp3SearchModule { @@ -442,7 +442,7 @@ func (c *baseClient) _process(ctx context.Context, cmd Cmder, attempt int) (bool } readReplyFunc := cmd.readReply // Apply unstable RESP3 search module. - if c.opt.Protocol != 2 && c.assertStableCommand(cmd) { + if c.opt.Protocol != 2 && c.assertUnstableCommand(cmd) { readReplyFunc = cmd.readRawReply } if err := cn.WithReader(c.context(ctx), c.cmdTimeout(cmd), readReplyFunc); err != nil { From 376a37f37de30339d3236f7454496ff21e5858de Mon Sep 17 00:00:00 2001 From: ofekshenawa Date: Tue, 3 Sep 2024 14:03:13 +0300 Subject: [PATCH 13/14] update errors --- README.md | 2 +- redis.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e919f1d2f..05f8ab436 100644 --- a/README.md +++ b/README.md @@ -183,7 +183,7 @@ rdb := redis.NewClient(&redis.Options{ ``` #### Unstable RESP3 Structures for RediSearch Commands -When connecting with Redis using RESP3 protocol, it's important to note that some response structures aren't final yet. This is the case for more complex structures in FT.SEARCH, FT.AGGREGATE, FT.Info, FT.SpellCheck and FT.SynDump. We recommend using RESP2 when using these commands, but we plan to stabilize the RESP3-based APIs in the coming versions. You can find more guidance in the upcoming release notes. +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. ## Contributing diff --git a/redis.go b/redis.go index 231c2c3e4..c5e2e6988 100644 --- a/redis.go +++ b/redis.go @@ -418,7 +418,7 @@ func (c *baseClient) assertUnstableCommand(cmd Cmder) bool { if c.opt.UnstableResp3SearchModule { return true } else { - panic("Some RESP3 results for Redis Query Engine responses may change. Refer to the readme for guidance") + panic("RESP3 responses for this command are disabled because they may still change. Please set the flag UnstableResp3SearchModule . See the [README](https://github.com/redis/go-redis/blob/master/README.md) and the release notes for guidance.") } default: return false From 92ba1d7a28e12bf8b0bbc0d04387a5cdde9e6640 Mon Sep 17 00:00:00 2001 From: vladvildanov Date: Thu, 12 Sep 2024 10:35:07 +0300 Subject: [PATCH 14/14] Rename flag to UnstableResp3 --- options.go | 2 +- redis.go | 4 ++-- ring.go | 12 ++++++------ search_test.go | 14 +++++++------- sentinel.go | 18 +++++++++--------- universal.go | 18 +++++++++--------- 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/options.go b/options.go index f7fd4c16c..8ba74ccd1 100644 --- a/options.go +++ b/options.go @@ -155,7 +155,7 @@ type Options struct { IdentitySuffix string // Enable Unstable mode for Redis Search module with RESP3. - UnstableResp3SearchModule bool + UnstableResp3 bool } func (opt *Options) init() { diff --git a/redis.go b/redis.go index c5e2e6988..c8b500809 100644 --- a/redis.go +++ b/redis.go @@ -415,10 +415,10 @@ func (c *baseClient) process(ctx context.Context, cmd Cmder) error { func (c *baseClient) assertUnstableCommand(cmd Cmder) bool { switch cmd.(type) { case *AggregateCmd, *FTInfoCmd, *FTSpellCheckCmd, *FTSearchCmd, *FTSynDumpCmd: - if c.opt.UnstableResp3SearchModule { + if c.opt.UnstableResp3 { return true } else { - panic("RESP3 responses for this command are disabled because they may still change. Please set the flag UnstableResp3SearchModule . See the [README](https://github.com/redis/go-redis/blob/master/README.md) and the release notes for guidance.") + 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.") } default: return false diff --git a/ring.go b/ring.go index 5768e90b3..b40221734 100644 --- a/ring.go +++ b/ring.go @@ -98,9 +98,9 @@ type RingOptions struct { TLSConfig *tls.Config Limiter Limiter - DisableIndentity bool - IdentitySuffix string - UnstableResp3SearchModule bool + DisableIndentity bool + IdentitySuffix string + UnstableResp3 bool } func (opt *RingOptions) init() { @@ -167,9 +167,9 @@ func (opt *RingOptions) clientOptions() *Options { TLSConfig: opt.TLSConfig, Limiter: opt.Limiter, - DisableIndentity: opt.DisableIndentity, - IdentitySuffix: opt.IdentitySuffix, - UnstableResp3SearchModule: opt.UnstableResp3SearchModule, + DisableIndentity: opt.DisableIndentity, + IdentitySuffix: opt.IdentitySuffix, + UnstableResp3: opt.UnstableResp3, } } diff --git a/search_test.go b/search_test.go index b4617a54f..93859a4e7 100644 --- a/search_test.go +++ b/search_test.go @@ -1424,7 +1424,7 @@ var _ = Describe("RediSearch commands Resp 3", Label("search"), func() { var client2 *redis.Client BeforeEach(func() { - client = redis.NewClient(&redis.Options{Addr: ":6379", Protocol: 3, UnstableResp3SearchModule: true}) + client = redis.NewClient(&redis.Options{Addr: ":6379", Protocol: 3, UnstableResp3: true}) client2 = redis.NewClient(&redis.Options{Addr: ":6379", Protocol: 3}) Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred()) }) @@ -1456,7 +1456,7 @@ var _ = Describe("RediSearch commands Resp 3", Label("search"), func() { Expect(results[1].(map[interface{}]interface{})["extra_attributes"].(map[interface{}]interface{})["CreatedDateTimeUTC"]). To(Or(BeEquivalentTo("6373878785249699840"), BeEquivalentTo("6373878758592700416"))) - // Test with UnstableResp3SearchModule false + // Test with UnstableResp3 false Expect(func() { options = &redis.FTAggregateOptions{Apply: []redis.FTAggregateApply{{Field: "@CreatedDateTimeUTC * 10", As: "CreatedDateTimeUTC"}}} rawRes, _ := client2.FTAggregateWithArgs(ctx, "idx1", "*", options).RawResult() @@ -1484,7 +1484,7 @@ var _ = Describe("RediSearch commands Resp 3", Label("search"), func() { flags = attributes[0].(map[interface{}]interface{})["flags"].([]interface{}) Expect(flags).To(ConsistOf("SORTABLE", "NOSTEM")) - // Test with UnstableResp3SearchModule false + // Test with UnstableResp3 false Expect(func() { rawResInfo, _ := client2.FTInfo(ctx, "idx1").RawResult() rawValInfo := client2.FTInfo(ctx, "idx1").RawVal() @@ -1511,7 +1511,7 @@ var _ = Describe("RediSearch commands Resp 3", Label("search"), func() { results := resSpellCheck.(map[interface{}]interface{})["results"].(map[interface{}]interface{}) Expect(results["impornant"].([]interface{})[0].(map[interface{}]interface{})["important"]).To(BeEquivalentTo(0.5)) - // Test with UnstableResp3SearchModule false + // Test with UnstableResp3 false Expect(func() { rawResSpellCheck, _ := client2.FTSpellCheck(ctx, "idx1", "impornant").RawResult() rawValSpellCheck := client2.FTSpellCheck(ctx, "idx1", "impornant").RawVal() @@ -1538,7 +1538,7 @@ var _ = Describe("RediSearch commands Resp 3", Label("search"), func() { totalResults2 := res2.(map[interface{}]interface{})["total_results"] Expect(totalResults2).To(BeEquivalentTo(int64(1))) - // Test with UnstableResp3SearchModule false + // Test with UnstableResp3 false Expect(func() { rawRes2, _ := client2.FTSearchWithArgs(ctx, "txt", "foo bar hello world", &redis.FTSearchOptions{NoContent: true}).RawResult() rawVal2 := client2.FTSearchWithArgs(ctx, "txt", "foo bar hello world", &redis.FTSearchOptions{NoContent: true}).RawVal() @@ -1572,7 +1572,7 @@ var _ = Describe("RediSearch commands Resp 3", Label("search"), func() { Expect(valSynDump).To(BeEquivalentTo(resSynDump)) Expect(resSynDump.(map[interface{}]interface{})["baby"]).To(BeEquivalentTo([]interface{}{"id1"})) - // Test with UnstableResp3SearchModule false + // Test with UnstableResp3 false Expect(func() { rawResSynDump, _ := client2.FTSynDump(ctx, "idx1").RawResult() rawValSynDump := client2.FTSynDump(ctx, "idx1").RawVal() @@ -1593,7 +1593,7 @@ var _ = Describe("RediSearch commands Resp 3", Label("search"), func() { Expect(err).NotTo(HaveOccurred()) Expect(res1).ToNot(BeEmpty()) - // Test with UnstableResp3SearchModule false + // Test with UnstableResp3 false Expect(func() { res2, err := client2.FTExplain(ctx, "txt", "@f3:f3_val @f2:f2_val @f1:f1_val").Result() Expect(err).NotTo(HaveOccurred()) diff --git a/sentinel.go b/sentinel.go index 925d76065..315695544 100644 --- a/sentinel.go +++ b/sentinel.go @@ -80,9 +80,9 @@ type FailoverOptions struct { TLSConfig *tls.Config - DisableIndentity bool - IdentitySuffix string - UnstableResp3SearchModule bool + DisableIndentity bool + IdentitySuffix string + UnstableResp3 bool } func (opt *FailoverOptions) clientOptions() *Options { @@ -118,9 +118,9 @@ func (opt *FailoverOptions) clientOptions() *Options { TLSConfig: opt.TLSConfig, - DisableIndentity: opt.DisableIndentity, - IdentitySuffix: opt.IdentitySuffix, - UnstableResp3SearchModule: opt.UnstableResp3SearchModule, + DisableIndentity: opt.DisableIndentity, + IdentitySuffix: opt.IdentitySuffix, + UnstableResp3: opt.UnstableResp3, } } @@ -156,9 +156,9 @@ func (opt *FailoverOptions) sentinelOptions(addr string) *Options { TLSConfig: opt.TLSConfig, - DisableIndentity: opt.DisableIndentity, - IdentitySuffix: opt.IdentitySuffix, - UnstableResp3SearchModule: opt.UnstableResp3SearchModule, + DisableIndentity: opt.DisableIndentity, + IdentitySuffix: opt.IdentitySuffix, + UnstableResp3: opt.UnstableResp3, } } diff --git a/universal.go b/universal.go index eae365e5d..f4d2d7598 100644 --- a/universal.go +++ b/universal.go @@ -66,9 +66,9 @@ type UniversalOptions struct { MasterName string - DisableIndentity bool - IdentitySuffix string - UnstableResp3SearchModule bool + DisableIndentity bool + IdentitySuffix string + UnstableResp3 bool } // Cluster returns cluster options created from the universal options. @@ -159,9 +159,9 @@ func (o *UniversalOptions) Failover() *FailoverOptions { TLSConfig: o.TLSConfig, - DisableIndentity: o.DisableIndentity, - IdentitySuffix: o.IdentitySuffix, - UnstableResp3SearchModule: o.UnstableResp3SearchModule, + DisableIndentity: o.DisableIndentity, + IdentitySuffix: o.IdentitySuffix, + UnstableResp3: o.UnstableResp3, } } @@ -203,9 +203,9 @@ func (o *UniversalOptions) Simple() *Options { TLSConfig: o.TLSConfig, - DisableIndentity: o.DisableIndentity, - IdentitySuffix: o.IdentitySuffix, - UnstableResp3SearchModule: o.UnstableResp3SearchModule, + DisableIndentity: o.DisableIndentity, + IdentitySuffix: o.IdentitySuffix, + UnstableResp3: o.UnstableResp3, } }