Skip to content

Commit 7532edf

Browse files
authored
Merge branch 'master' into redundant-dial-mutex
2 parents 8975e1e + 930d904 commit 7532edf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+9259
-2491
lines changed

.github/wordlist.txt

+6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
ACLs
2+
APIs
23
autoload
34
autoloader
45
autoloading
@@ -46,11 +47,14 @@ runtime
4647
SHA
4748
sharding
4849
SETNAME
50+
SpellCheck
4951
SSL
5052
struct
5153
stunnel
54+
SynDump
5255
TCP
5356
TLS
57+
UnstableResp
5458
uri
5559
URI
5660
url
@@ -59,3 +63,5 @@ RedisStack
5963
RedisGears
6064
RedisTimeseries
6165
RediSearch
66+
RawResult
67+
RawVal

.github/workflows/build.yml

+6
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,9 @@ jobs:
3737

3838
- name: Test
3939
run: make test
40+
41+
- name: Upload to Codecov
42+
uses: codecov/codecov-action@v4
43+
with:
44+
files: coverage.txt
45+
token: ${{ secrets.CODECOV_TOKEN }}

Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ test: testdeps
1414
go test ./... -short -race && \
1515
go test ./... -run=NONE -bench=. -benchmem && \
1616
env GOOS=linux GOARCH=386 go test && \
17+
go test -coverprofile=coverage.txt -covermode=atomic ./... && \
1718
go vet); \
1819
done
1920
cd internal/customvet && go build .

README.md

+19
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
[![build workflow](https://github.com/redis/go-redis/actions/workflows/build.yml/badge.svg)](https://github.com/redis/go-redis/actions)
44
[![PkgGoDev](https://pkg.go.dev/badge/github.com/redis/go-redis/v9)](https://pkg.go.dev/github.com/redis/go-redis/v9?tab=doc)
55
[![Documentation](https://img.shields.io/badge/redis-documentation-informational)](https://redis.uptrace.dev/)
6+
[![codecov](https://codecov.io/github/redis/go-redis/graph/badge.svg?token=tsrCZKuSSw)](https://codecov.io/github/redis/go-redis)
67
[![Chat](https://discordapp.com/api/guilds/752070105847955518/widget.png)](https://discord.gg/rWtp5Aj)
78

89
> go-redis is brought to you by :star: [**uptrace/uptrace**](https://github.com/uptrace/uptrace).
@@ -182,6 +183,24 @@ rdb := redis.NewClient(&redis.Options{
182183
})
183184
```
184185

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+
189+
To enable unstable RESP3, set the option in your client configuration:
190+
191+
```go
192+
redis.NewClient(&redis.Options{
193+
UnstableResp3: true,
194+
})
195+
```
196+
**Note:** When UnstableResp3 mode is enabled, it's necessary to use RawResult() and RawVal() to retrieve a raw data.
197+
Since, raw response is the only option for unstable search commands Val() and Result() calls wouldn't have any affect on them:
198+
199+
```go
200+
res1, err := client.FTSearchWithArgs(ctx, "txt", "foo bar", &redis.FTSearchOptions{}).RawResult()
201+
val1 := client.FTSearchWithArgs(ctx, "txt", "foo bar", &redis.FTSearchOptions{}).RawVal()
202+
```
203+
185204
## Contributing
186205

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

command.go

+56-15
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 {
@@ -1398,27 +1403,63 @@ func (cmd *MapStringSliceInterfaceCmd) Val() map[string][]interface{} {
13981403
}
13991404

14001405
func (cmd *MapStringSliceInterfaceCmd) readReply(rd *proto.Reader) (err error) {
1401-
n, err := rd.ReadMapLen()
1406+
readType, err := rd.PeekReplyType()
14021407
if err != nil {
14031408
return err
14041409
}
1405-
cmd.val = make(map[string][]interface{}, n)
1406-
for i := 0; i < n; i++ {
1407-
k, err := rd.ReadString()
1410+
1411+
cmd.val = make(map[string][]interface{})
1412+
1413+
if readType == proto.RespMap {
1414+
n, err := rd.ReadMapLen()
14081415
if err != nil {
14091416
return err
14101417
}
1411-
nn, err := rd.ReadArrayLen()
1418+
for i := 0; i < n; i++ {
1419+
k, err := rd.ReadString()
1420+
if err != nil {
1421+
return err
1422+
}
1423+
nn, err := rd.ReadArrayLen()
1424+
if err != nil {
1425+
return err
1426+
}
1427+
cmd.val[k] = make([]interface{}, nn)
1428+
for j := 0; j < nn; j++ {
1429+
value, err := rd.ReadReply()
1430+
if err != nil {
1431+
return err
1432+
}
1433+
cmd.val[k][j] = value
1434+
}
1435+
}
1436+
} else if readType == proto.RespArray {
1437+
// RESP2 response
1438+
n, err := rd.ReadArrayLen()
14121439
if err != nil {
14131440
return err
14141441
}
1415-
cmd.val[k] = make([]interface{}, nn)
1416-
for j := 0; j < nn; j++ {
1417-
value, err := rd.ReadReply()
1442+
1443+
for i := 0; i < n; i++ {
1444+
// Each entry in this array is itself an array with key details
1445+
itemLen, err := rd.ReadArrayLen()
14181446
if err != nil {
14191447
return err
14201448
}
1421-
cmd.val[k][j] = value
1449+
1450+
key, err := rd.ReadString()
1451+
if err != nil {
1452+
return err
1453+
}
1454+
cmd.val[key] = make([]interface{}, 0, itemLen-1)
1455+
for j := 1; j < itemLen; j++ {
1456+
// Read the inner array for timestamp-value pairs
1457+
data, err := rd.ReadReply()
1458+
if err != nil {
1459+
return err
1460+
}
1461+
cmd.val[key] = append(cmd.val[key], data)
1462+
}
14221463
}
14231464
}
14241465

doctests/bf_tutorial_test.go

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// EXAMPLE: bf_tutorial
2+
// HIDE_START
3+
package example_commands_test
4+
5+
import (
6+
"context"
7+
"fmt"
8+
9+
"github.com/redis/go-redis/v9"
10+
)
11+
12+
// HIDE_END
13+
14+
func ExampleClient_bloom() {
15+
ctx := context.Background()
16+
17+
rdb := redis.NewClient(&redis.Options{
18+
Addr: "localhost:6379",
19+
Password: "", // no password docs
20+
DB: 0, // use default DB
21+
})
22+
23+
// REMOVE_START
24+
rdb.Del(ctx, "bikes:models")
25+
// REMOVE_END
26+
27+
// STEP_START bloom
28+
res1, err := rdb.BFReserve(ctx, "bikes:models", 0.01, 1000).Result()
29+
30+
if err != nil {
31+
panic(err)
32+
}
33+
34+
fmt.Println(res1) // >>> OK
35+
36+
res2, err := rdb.BFAdd(ctx, "bikes:models", "Smoky Mountain Striker").Result()
37+
38+
if err != nil {
39+
panic(err)
40+
}
41+
42+
fmt.Println(res2) // >>> true
43+
44+
res3, err := rdb.BFExists(ctx, "bikes:models", "Smoky Mountain Striker").Result()
45+
46+
if err != nil {
47+
panic(err)
48+
}
49+
50+
fmt.Println(res3) // >>> true
51+
52+
res4, err := rdb.BFMAdd(ctx, "bikes:models",
53+
"Rocky Mountain Racer",
54+
"Cloudy City Cruiser",
55+
"Windy City Wippet",
56+
).Result()
57+
58+
if err != nil {
59+
panic(err)
60+
}
61+
62+
fmt.Println(res4) // >>> [true true true]
63+
64+
res5, err := rdb.BFMExists(ctx, "bikes:models",
65+
"Rocky Mountain Racer",
66+
"Cloudy City Cruiser",
67+
"Windy City Wippet",
68+
).Result()
69+
70+
if err != nil {
71+
panic(err)
72+
}
73+
74+
fmt.Println(res5) // >>> [true true true]
75+
// STEP_END
76+
77+
// Output:
78+
// OK
79+
// true
80+
// true
81+
// [true true true]
82+
// [true true true]
83+
}

doctests/bitfield_tutorial_test.go

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// EXAMPLE: bitfield_tutorial
2+
// HIDE_START
3+
package example_commands_test
4+
5+
import (
6+
"context"
7+
"fmt"
8+
9+
"github.com/redis/go-redis/v9"
10+
)
11+
12+
// HIDE_END
13+
14+
func ExampleClient_bf() {
15+
ctx := context.Background()
16+
17+
rdb := redis.NewClient(&redis.Options{
18+
Addr: "localhost:6379",
19+
Password: "", // no password docs
20+
DB: 0, // use default DB
21+
})
22+
23+
// REMOVE_START
24+
rdb.Del(ctx, "bike:1:stats")
25+
// REMOVE_END
26+
27+
// STEP_START bf
28+
res1, err := rdb.BitField(ctx, "bike:1:stats",
29+
"set", "u32", "#0", "1000",
30+
).Result()
31+
32+
if err != nil {
33+
panic(err)
34+
}
35+
36+
fmt.Println(res1) // >>> [0]
37+
38+
res2, err := rdb.BitField(ctx,
39+
"bike:1:stats",
40+
"incrby", "u32", "#0", "-50",
41+
"incrby", "u32", "#1", "1",
42+
).Result()
43+
44+
if err != nil {
45+
panic(err)
46+
}
47+
48+
fmt.Println(res2) // >>> [950 1]
49+
50+
res3, err := rdb.BitField(ctx,
51+
"bike:1:stats",
52+
"incrby", "u32", "#0", "500",
53+
"incrby", "u32", "#1", "1",
54+
).Result()
55+
56+
if err != nil {
57+
panic(err)
58+
}
59+
60+
fmt.Println(res3) // >>> [1450 2]
61+
62+
res4, err := rdb.BitField(ctx, "bike:1:stats",
63+
"get", "u32", "#0",
64+
"get", "u32", "#1",
65+
).Result()
66+
67+
if err != nil {
68+
panic(err)
69+
}
70+
71+
fmt.Println(res4) // >>> [1450 2]
72+
// STEP_END
73+
74+
// Output:
75+
// [0]
76+
// [950 1]
77+
// [1450 2]
78+
// [1450 2]
79+
}

0 commit comments

Comments
 (0)