Skip to content

Commit 9ede562

Browse files
authored
Merge branch 'master' into DOC-4464-list-cmd-examples
2 parents 5005cf7 + 1c9309f commit 9ede562

File tree

10 files changed

+168
-9
lines changed

10 files changed

+168
-9
lines changed

README.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,7 @@
66
[![codecov](https://codecov.io/github/redis/go-redis/graph/badge.svg?token=tsrCZKuSSw)](https://codecov.io/github/redis/go-redis)
77
[![Chat](https://discordapp.com/api/guilds/752070105847955518/widget.png)](https://discord.gg/rWtp5Aj)
88

9-
> go-redis is brought to you by :star: [**uptrace/uptrace**](https://github.com/uptrace/uptrace).
10-
> Uptrace is an open-source APM tool that supports distributed tracing, metrics, and logs. You can
11-
> use it to monitor applications and set up automatic alerts to receive notifications via email,
12-
> Slack, Telegram, and others.
13-
>
14-
> See [OpenTelemetry](https://github.com/redis/go-redis/tree/master/example/otel) example which
15-
> demonstrates how you can use Uptrace to monitor go-redis.
9+
> go-redis is the official Redis client library for the Go programming language. It offers a straightforward interface for interacting with Redis servers.
1610
1711
## Supported versions
1812

@@ -215,6 +209,10 @@ res1, err := client.FTSearchWithArgs(ctx, "txt", "foo bar", &redis.FTSearchOptio
215209
val1 := client.FTSearchWithArgs(ctx, "txt", "foo bar", &redis.FTSearchOptions{}).RawVal()
216210
```
217211

212+
#### Redis-Search Default Dialect
213+
214+
In the Redis-Search module, **the default dialect is 2**. If needed, you can explicitly specify a different dialect using the appropriate configuration in your queries.
215+
218216
## Contributing
219217

220218
Please see [out contributing guidelines](CONTRIBUTING.md) to help us improve this library!
@@ -297,6 +295,14 @@ REDIS_PORT=9999 go test <your options>
297295

298296
## Contributors
299297

298+
> The go-redis project was originally initiated by :star: [**uptrace/uptrace**](https://github.com/uptrace/uptrace).
299+
> Uptrace is an open-source APM tool that supports distributed tracing, metrics, and logs. You can
300+
> use it to monitor applications and set up automatic alerts to receive notifications via email,
301+
> Slack, Telegram, and others.
302+
>
303+
> See [OpenTelemetry](https://github.com/redis/go-redis/tree/master/example/otel) example which
304+
> demonstrates how you can use Uptrace to monitor go-redis.
305+
300306
Thanks to all the people who already contributed!
301307

302308
<a href="https://github.com/redis/go-redis/graphs/contributors">

error.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ type Error interface {
3838

3939
var _ Error = proto.RedisError("")
4040

41+
func isContextError(err error) bool {
42+
switch err {
43+
case context.Canceled, context.DeadlineExceeded:
44+
return true
45+
default:
46+
return false
47+
}
48+
}
49+
4150
func shouldRetry(err error, retryTimeout bool) bool {
4251
switch err {
4352
case io.EOF, io.ErrUnexpectedEOF:

osscluster.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1350,7 +1350,9 @@ func (c *ClusterClient) processPipelineNode(
13501350
_ = node.Client.withProcessPipelineHook(ctx, cmds, func(ctx context.Context, cmds []Cmder) error {
13511351
cn, err := node.Client.getConn(ctx)
13521352
if err != nil {
1353-
node.MarkAsFailing()
1353+
if !isContextError(err) {
1354+
node.MarkAsFailing()
1355+
}
13541356
_ = c.mapCmdsByNode(ctx, failedCmds, cmds)
13551357
setCmdsErr(cmds, err)
13561358
return err

osscluster_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,39 @@ var _ = Describe("ClusterClient", func() {
539539
AfterEach(func() {})
540540

541541
assertPipeline()
542+
543+
It("doesn't fail node with context.Canceled error", func() {
544+
ctx, cancel := context.WithCancel(context.Background())
545+
cancel()
546+
pipe.Set(ctx, "A", "A_value", 0)
547+
_, err := pipe.Exec(ctx)
548+
549+
Expect(err).To(HaveOccurred())
550+
Expect(errors.Is(err, context.Canceled)).To(BeTrue())
551+
552+
clientNodes, _ := client.Nodes(ctx, "A")
553+
554+
for _, node := range clientNodes {
555+
Expect(node.Failing()).To(BeFalse())
556+
}
557+
})
558+
559+
It("doesn't fail node with context.DeadlineExceeded error", func() {
560+
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Nanosecond)
561+
defer cancel()
562+
563+
pipe.Set(ctx, "A", "A_value", 0)
564+
_, err := pipe.Exec(ctx)
565+
566+
Expect(err).To(HaveOccurred())
567+
Expect(errors.Is(err, context.DeadlineExceeded)).To(BeTrue())
568+
569+
clientNodes, _ := client.Nodes(ctx, "A")
570+
571+
for _, node := range clientNodes {
572+
Expect(node.Failing()).To(BeFalse())
573+
}
574+
})
542575
})
543576

544577
Describe("with TxPipeline", func() {

redis.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ func (c *baseClient) initConn(ctx context.Context, cn *pool.Conn) error {
310310

311311
// for redis-server versions that do not support the HELLO command,
312312
// RESP2 will continue to be used.
313-
if err = conn.Hello(ctx, protocol, username, password, "").Err(); err == nil {
313+
if err = conn.Hello(ctx, protocol, username, password, c.opt.ClientName).Err(); err == nil {
314314
auth = true
315315
} else if !isRedisError(err) {
316316
// When the server responds with the RESP protocol and the result is not a normal

redis_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,32 @@ var _ = Describe("Client", func() {
186186
Expect(val).Should(ContainSubstring("name=hi"))
187187
})
188188

189+
It("should attempt to set client name in HELLO", func() {
190+
opt := redisOptions()
191+
opt.ClientName = "hi"
192+
db := redis.NewClient(opt)
193+
194+
defer func() {
195+
Expect(db.Close()).NotTo(HaveOccurred())
196+
}()
197+
198+
// Client name should be already set on any successfully initialized connection
199+
name, err := db.ClientGetName(ctx).Result()
200+
Expect(err).NotTo(HaveOccurred())
201+
Expect(name).Should(Equal("hi"))
202+
203+
// HELLO should be able to explicitly overwrite the client name
204+
conn := db.Conn()
205+
hello, err := conn.Hello(ctx, 3, "", "", "hi2").Result()
206+
Expect(err).NotTo(HaveOccurred())
207+
Expect(hello["proto"]).Should(Equal(int64(3)))
208+
name, err = conn.ClientGetName(ctx).Result()
209+
Expect(err).NotTo(HaveOccurred())
210+
Expect(name).Should(Equal("hi2"))
211+
err = conn.Close()
212+
Expect(err).NotTo(HaveOccurred())
213+
})
214+
189215
It("should client PROTO 2", func() {
190216
opt := redisOptions()
191217
opt.Protocol = 2

search_commands.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,8 @@ func FTAggregateQuery(query string, options *FTAggregateOptions) AggregateQuery
604604

605605
if options.DialectVersion > 0 {
606606
queryArgs = append(queryArgs, "DIALECT", options.DialectVersion)
607+
} else {
608+
queryArgs = append(queryArgs, "DIALECT", 2)
607609
}
608610
}
609611
return queryArgs
@@ -801,6 +803,8 @@ func (c cmdable) FTAggregateWithArgs(ctx context.Context, index string, query st
801803
}
802804
if options.DialectVersion > 0 {
803805
args = append(args, "DIALECT", options.DialectVersion)
806+
} else {
807+
args = append(args, "DIALECT", 2)
804808
}
805809
}
806810

@@ -1174,6 +1178,8 @@ func (c cmdable) FTExplainWithArgs(ctx context.Context, index string, query stri
11741178
args := []interface{}{"FT.EXPLAIN", index, query}
11751179
if options.Dialect != "" {
11761180
args = append(args, "DIALECT", options.Dialect)
1181+
} else {
1182+
args = append(args, "DIALECT", 2)
11771183
}
11781184
cmd := NewStringCmd(ctx, args...)
11791185
_ = c(ctx, cmd)
@@ -1471,6 +1477,8 @@ func (c cmdable) FTSpellCheckWithArgs(ctx context.Context, index string, query s
14711477
}
14721478
if options.Dialect > 0 {
14731479
args = append(args, "DIALECT", options.Dialect)
1480+
} else {
1481+
args = append(args, "DIALECT", 2)
14741482
}
14751483
}
14761484
cmd := newFTSpellCheckCmd(ctx, args...)
@@ -1840,6 +1848,8 @@ func FTSearchQuery(query string, options *FTSearchOptions) SearchQuery {
18401848
}
18411849
if options.DialectVersion > 0 {
18421850
queryArgs = append(queryArgs, "DIALECT", options.DialectVersion)
1851+
} else {
1852+
queryArgs = append(queryArgs, "DIALECT", 2)
18431853
}
18441854
}
18451855
return queryArgs
@@ -1955,6 +1965,8 @@ func (c cmdable) FTSearchWithArgs(ctx context.Context, index string, query strin
19551965
}
19561966
if options.DialectVersion > 0 {
19571967
args = append(args, "DIALECT", options.DialectVersion)
1968+
} else {
1969+
args = append(args, "DIALECT", 2)
19581970
}
19591971
}
19601972
cmd := newFTSearchCmd(ctx, options, args...)

search_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,6 +1143,55 @@ var _ = Describe("RediSearch commands Resp 2", Label("search"), func() {
11431143
Expect(res.Docs[0].Fields["__v_score"]).To(BeEquivalentTo("0"))
11441144
})
11451145

1146+
It("should FTCreate VECTOR with dialect 1 ", Label("search", "ftcreate"), func() {
1147+
hnswOptions := &redis.FTHNSWOptions{Type: "FLOAT32", Dim: 2, DistanceMetric: "L2"}
1148+
val, err := client.FTCreate(ctx, "idx1",
1149+
&redis.FTCreateOptions{},
1150+
&redis.FieldSchema{FieldName: "v", FieldType: redis.SearchFieldTypeVector, VectorArgs: &redis.FTVectorArgs{HNSWOptions: hnswOptions}}).Result()
1151+
Expect(err).NotTo(HaveOccurred())
1152+
Expect(val).To(BeEquivalentTo("OK"))
1153+
WaitForIndexing(client, "idx1")
1154+
1155+
client.HSet(ctx, "a", "v", "aaaaaaaa")
1156+
client.HSet(ctx, "b", "v", "aaaabaaa")
1157+
client.HSet(ctx, "c", "v", "aaaaabaa")
1158+
1159+
searchOptions := &redis.FTSearchOptions{
1160+
Return: []redis.FTSearchReturn{{FieldName: "v"}},
1161+
SortBy: []redis.FTSearchSortBy{{FieldName: "v", Asc: true}},
1162+
Limit: 10,
1163+
DialectVersion: 1,
1164+
}
1165+
res, err := client.FTSearchWithArgs(ctx, "idx1", "*", searchOptions).Result()
1166+
Expect(err).NotTo(HaveOccurred())
1167+
Expect(res.Docs[0].ID).To(BeEquivalentTo("a"))
1168+
Expect(res.Docs[0].Fields["v"]).To(BeEquivalentTo("aaaaaaaa"))
1169+
})
1170+
1171+
It("should FTCreate VECTOR with default dialect", Label("search", "ftcreate"), func() {
1172+
hnswOptions := &redis.FTHNSWOptions{Type: "FLOAT32", Dim: 2, DistanceMetric: "L2"}
1173+
val, err := client.FTCreate(ctx, "idx1",
1174+
&redis.FTCreateOptions{},
1175+
&redis.FieldSchema{FieldName: "v", FieldType: redis.SearchFieldTypeVector, VectorArgs: &redis.FTVectorArgs{HNSWOptions: hnswOptions}}).Result()
1176+
Expect(err).NotTo(HaveOccurred())
1177+
Expect(val).To(BeEquivalentTo("OK"))
1178+
WaitForIndexing(client, "idx1")
1179+
1180+
client.HSet(ctx, "a", "v", "aaaaaaaa")
1181+
client.HSet(ctx, "b", "v", "aaaabaaa")
1182+
client.HSet(ctx, "c", "v", "aaaaabaa")
1183+
1184+
searchOptions := &redis.FTSearchOptions{
1185+
Return: []redis.FTSearchReturn{{FieldName: "__v_score"}},
1186+
SortBy: []redis.FTSearchSortBy{{FieldName: "__v_score", Asc: true}},
1187+
Params: map[string]interface{}{"vec": "aaaaaaaa"},
1188+
}
1189+
res, err := client.FTSearchWithArgs(ctx, "idx1", "*=>[KNN 2 @v $vec]", searchOptions).Result()
1190+
Expect(err).NotTo(HaveOccurred())
1191+
Expect(res.Docs[0].ID).To(BeEquivalentTo("a"))
1192+
Expect(res.Docs[0].Fields["__v_score"]).To(BeEquivalentTo("0"))
1193+
})
1194+
11461195
It("should FTCreate and FTSearch text params", Label("search", "ftcreate", "ftsearch"), func() {
11471196
val, err := client.FTCreate(ctx, "idx1", &redis.FTCreateOptions{}, &redis.FieldSchema{FieldName: "name", FieldType: redis.SearchFieldTypeText}).Result()
11481197
Expect(err).NotTo(HaveOccurred())

universal.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ func (o *UniversalOptions) Failover() *FailoverOptions {
163163

164164
TLSConfig: o.TLSConfig,
165165

166+
ReplicaOnly: o.ReadOnly,
167+
166168
DisableIndentity: o.DisableIndentity,
167169
IdentitySuffix: o.IdentitySuffix,
168170
UnstableResp3: o.UnstableResp3,

universal_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,25 @@ var _ = Describe("UniversalClient", func() {
6060
Expect(a).ToNot(Panic())
6161
})
6262

63+
It("should connect to failover servers on slaves when readonly Options is ok", Label("NonRedisEnterprise"), func() {
64+
client = redis.NewUniversalClient(&redis.UniversalOptions{
65+
MasterName: sentinelName,
66+
Addrs: sentinelAddrs,
67+
ReadOnly: true,
68+
})
69+
Expect(client.Ping(ctx).Err()).NotTo(HaveOccurred())
70+
71+
roleCmd := client.Do(ctx, "ROLE")
72+
role, err := roleCmd.Result()
73+
Expect(err).NotTo(HaveOccurred())
74+
75+
roleSlice, ok := role.([]interface{})
76+
Expect(ok).To(BeTrue())
77+
Expect(roleSlice[0]).To(Equal("slave"))
78+
79+
err = client.Set(ctx, "somekey", "somevalue", 0).Err()
80+
Expect(err).To(HaveOccurred())
81+
})
6382
It("should connect to clusters if IsClusterMode is set even if only a single address is provided", Label("NonRedisEnterprise"), func() {
6483
client = redis.NewUniversalClient(&redis.UniversalOptions{
6584
Addrs: []string{cluster.addrs()[0]},
@@ -77,3 +96,4 @@ var _ = Describe("UniversalClient", func() {
7796
Expect(client.ClusterSlots(ctx).Val()).To(HaveLen(3))
7897
})
7998
})
99+

0 commit comments

Comments
 (0)