Skip to content

Commit 405c34c

Browse files
authored
Merge branch 'master' into add-int8-uint8-vector-types-tests
2 parents 486b6c2 + 9494d84 commit 405c34c

13 files changed

+177
-7
lines changed

Diff for: .github/actions/run-tests/action.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ runs:
2525
2626
# Mapping of redis version to redis testing containers
2727
declare -A redis_version_mapping=(
28-
["8.0-M03"]="8.0-M04-pre"
28+
["8.0-M05"]="8.0-M05-pre"
2929
["7.4.2"]="rs-7.4.0-v2"
3030
["7.2.7"]="rs-7.2.0-v14"
3131
)

Diff for: .github/workflows/build.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
fail-fast: false
1919
matrix:
2020
redis-version:
21-
- "8.0-M03" # 8.0 milestone 4
21+
- "8.0-M05" # 8.0 milestone 5
2222
- "7.4.2" # should use redis stack 7.4
2323
go-version:
2424
- "1.23.x"
@@ -43,7 +43,7 @@ jobs:
4343
4444
# Mapping of redis version to redis testing containers
4545
declare -A redis_version_mapping=(
46-
["8.0-M03"]="8.0-M04-pre"
46+
["8.0-M05"]="8.0-M05-pre"
4747
["7.4.2"]="rs-7.4.0-v2"
4848
)
4949
if [[ -v redis_version_mapping[$REDIS_VERSION] ]]; then
@@ -72,7 +72,7 @@ jobs:
7272
fail-fast: false
7373
matrix:
7474
redis-version:
75-
- "8.0-M03" # 8.0 milestone 4
75+
- "8.0-M05" # 8.0 milestone 5
7676
- "7.4.2" # should use redis stack 7.4
7777
- "7.2.7" # should redis stack 7.2
7878
go-version:

Diff for: .github/workflows/golangci-lint.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ jobs:
2121
steps:
2222
- uses: actions/checkout@v4
2323
- name: golangci-lint
24-
uses: golangci/[email protected].0
24+
uses: golangci/[email protected].1

Diff for: Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ test.ci:
1717
(cd "$${dir}" && \
1818
go mod tidy -compat=1.18 && \
1919
go vet && \
20-
go test -coverprofile=coverage.txt -covermode=atomic ./... -race); \
20+
go test -v -coverprofile=coverage.txt -covermode=atomic ./... -race); \
2121
done
2222
cd internal/customvet && go build .
2323
go vet -vettool ./internal/customvet/customvet

Diff for: README.md

+4
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,10 @@ res1, err := client.FTSearchWithArgs(ctx, "txt", "foo bar", &redis.FTSearchOptio
209209
val1 := client.FTSearchWithArgs(ctx, "txt", "foo bar", &redis.FTSearchOptions{}).RawVal()
210210
```
211211

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+
212216
## Contributing
213217

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

Diff for: docker-compose.yml

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
services:
44
redis:
55
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2}
6+
platform: linux/amd64
67
container_name: redis-standalone
78
environment:
89
- TLS_ENABLED=yes
@@ -23,6 +24,7 @@ services:
2324

2425
osscluster:
2526
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2}
27+
platform: linux/amd64
2628
container_name: redis-osscluster
2729
environment:
2830
- NODES=6
@@ -39,6 +41,7 @@ services:
3941

4042
sentinel-cluster:
4143
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2}
44+
platform: linux/amd64
4245
container_name: redis-sentinel-cluster
4346
network_mode: "host"
4447
environment:
@@ -58,6 +61,7 @@ services:
5861

5962
sentinel:
6063
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2}
64+
platform: linux/amd64
6165
container_name: redis-sentinel
6266
depends_on:
6367
- sentinel-cluster
@@ -81,6 +85,7 @@ services:
8185

8286
ring-cluster:
8387
image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2}
88+
platform: linux/amd64
8489
container_name: redis-ring-cluster
8590
environment:
8691
- NODES=3

Diff for: error.go

+3
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ func shouldRetry(err error, retryTimeout bool) bool {
5353
return true
5454
case nil, context.Canceled, context.DeadlineExceeded:
5555
return false
56+
case pool.ErrPoolTimeout:
57+
// connection pool timeout, increase retries. #3289
58+
return true
5659
}
5760

5861
if v, ok := err.(timeoutError); ok {

Diff for: error_test.go

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package redis_test
2+
3+
import (
4+
"context"
5+
"errors"
6+
"io"
7+
8+
. "github.com/bsm/ginkgo/v2"
9+
. "github.com/bsm/gomega"
10+
"github.com/redis/go-redis/v9"
11+
)
12+
13+
type testTimeout struct {
14+
timeout bool
15+
}
16+
17+
func (t testTimeout) Timeout() bool {
18+
return t.timeout
19+
}
20+
21+
func (t testTimeout) Error() string {
22+
return "test timeout"
23+
}
24+
25+
var _ = Describe("error", func() {
26+
BeforeEach(func() {
27+
28+
})
29+
30+
AfterEach(func() {
31+
32+
})
33+
34+
It("should retry", func() {
35+
data := map[error]bool{
36+
io.EOF: true,
37+
io.ErrUnexpectedEOF: true,
38+
nil: false,
39+
context.Canceled: false,
40+
context.DeadlineExceeded: false,
41+
redis.ErrPoolTimeout: true,
42+
errors.New("ERR max number of clients reached"): true,
43+
errors.New("LOADING Redis is loading the dataset in memory"): true,
44+
errors.New("READONLY You can't write against a read only replica"): true,
45+
errors.New("CLUSTERDOWN The cluster is down"): true,
46+
errors.New("TRYAGAIN Command cannot be processed, please try again"): true,
47+
errors.New("other"): false,
48+
}
49+
50+
for err, expected := range data {
51+
Expect(redis.ShouldRetry(err, false)).To(Equal(expected))
52+
Expect(redis.ShouldRetry(err, true)).To(Equal(expected))
53+
}
54+
})
55+
56+
It("should retry timeout", func() {
57+
t1 := testTimeout{timeout: true}
58+
Expect(redis.ShouldRetry(t1, true)).To(Equal(true))
59+
Expect(redis.ShouldRetry(t1, false)).To(Equal(false))
60+
61+
t2 := testTimeout{timeout: false}
62+
Expect(redis.ShouldRetry(t2, true)).To(Equal(true))
63+
Expect(redis.ShouldRetry(t2, false)).To(Equal(true))
64+
})
65+
})

Diff for: export_test.go

+6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
"github.com/redis/go-redis/v9/internal/pool"
1212
)
1313

14+
var ErrPoolTimeout = pool.ErrPoolTimeout
15+
1416
func (c *baseClient) Pool() pool.Pooler {
1517
return c.connPool
1618
}
@@ -102,3 +104,7 @@ func (c *Ring) ShardByName(name string) *ringShard {
102104
func (c *ModuleLoadexConfig) ToArgs() []interface{} {
103105
return c.toArgs()
104106
}
107+
108+
func ShouldRetry(err error, retryTimeout bool) bool {
109+
return shouldRetry(err, retryTimeout)
110+
}

Diff for: redis.go

+1-1
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

Diff for: redis_test.go

+26
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

Diff for: search_commands.go

+12
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...)

Diff for: search_test.go

+49
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())

0 commit comments

Comments
 (0)