Skip to content

Commit b0bb514

Browse files
committed
fix: update COMMAND parser for Redis 7
1 parent 3a722be commit b0bb514

File tree

6 files changed

+40
-27
lines changed

6 files changed

+40
-27
lines changed

bench_decode_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func NewClusterClientStub(resp []byte) *ClientStub {
4141

4242
client := NewClusterClient(&ClusterOptions{
4343
PoolSize: 128,
44-
Addrs: []string{"127.0.0.1:6379"},
44+
Addrs: []string{":6379"},
4545
Dialer: func(ctx context.Context, network, addr string) (net.Conn, error) {
4646
return stub.stubConn(initHello), nil
4747
},
@@ -118,7 +118,7 @@ func BenchmarkDecode(b *testing.B) {
118118
}
119119

120120
benchmarks := []Benchmark{
121-
{"single", NewClientStub},
121+
{"server", NewClientStub},
122122
{"cluster", NewClusterClientStub},
123123
}
124124

command.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int {
8383
if info != nil {
8484
return int(info.FirstKeyPos)
8585
}
86-
return 0
86+
return 1
8787
}
8888

8989
func cmdString(cmd Cmder, val interface{}) string {
@@ -3166,6 +3166,7 @@ func (cmd *CommandsInfoCmd) String() string {
31663166
func (cmd *CommandsInfoCmd) readReply(rd *proto.Reader) error {
31673167
const numArgRedis5 = 6
31683168
const numArgRedis6 = 7
3169+
const numArgRedis7 = 10
31693170

31703171
n, err := rd.ReadArrayLen()
31713172
if err != nil {
@@ -3178,8 +3179,12 @@ func (cmd *CommandsInfoCmd) readReply(rd *proto.Reader) error {
31783179
if err != nil {
31793180
return err
31803181
}
3181-
if nn != numArgRedis5 && nn != numArgRedis6 {
3182-
return fmt.Errorf("redis: got %d elements in COMMAND reply, wanted 6/7", nn)
3182+
3183+
switch nn {
3184+
case numArgRedis5, numArgRedis6, numArgRedis7:
3185+
// ok
3186+
default:
3187+
return fmt.Errorf("redis: got %d elements in COMMAND reply, wanted 6/7/10", nn)
31833188
}
31843189

31853190
cmdInfo := &CommandInfo{}
@@ -3230,7 +3235,7 @@ func (cmd *CommandsInfoCmd) readReply(rd *proto.Reader) error {
32303235
}
32313236
cmdInfo.StepCount = int8(stepCount)
32323237

3233-
if nn == numArgRedis6 {
3238+
if nn >= numArgRedis6 {
32343239
aclFlagLen, err := rd.ReadArrayLen()
32353240
if err != nil {
32363241
return err
@@ -3248,6 +3253,18 @@ func (cmd *CommandsInfoCmd) readReply(rd *proto.Reader) error {
32483253
}
32493254
}
32503255

3256+
if nn >= numArgRedis7 {
3257+
if err := rd.DiscardNext(); err != nil {
3258+
return err
3259+
}
3260+
if err := rd.DiscardNext(); err != nil {
3261+
return err
3262+
}
3263+
if err := rd.DiscardNext(); err != nil {
3264+
return err
3265+
}
3266+
}
3267+
32513268
cmd.val[cmdInfo.Name] = cmdInfo
32523269
}
32533270

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.17
44

55
require (
66
github.com/cespare/xxhash/v2 v2.1.2
7+
github.com/davecgh/go-spew v1.1.1
78
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f
89
github.com/onsi/ginkgo v1.16.5
910
github.com/onsi/gomega v1.19.0

go.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
44
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
55
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
66
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
7+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
78
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
89
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
910
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=

internal/proto/reader.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ func (r *Reader) ReadLine() ([]byte, error) {
124124
return line, nil
125125
}
126126

127-
// readLine that returns an error if:
127+
// readLine returns an error if:
128128
// - there is a pending read error;
129129
// - or line does not end with \r\n.
130130
func (r *Reader) readLine() ([]byte, error) {
@@ -403,7 +403,7 @@ func (r *Reader) ReadArrayLen() (int, error) {
403403
case RespArray, RespSet, RespPush:
404404
return replyLen(line)
405405
default:
406-
return 0, fmt.Errorf("redis: can't parse array(array/set/push) reply: %.100q", line)
406+
return 0, fmt.Errorf("redis: can't parse array/set/push reply: %.100q", line)
407407
}
408408
}
409409

@@ -446,6 +446,15 @@ func (r *Reader) ReadMapLen() (int, error) {
446446
}
447447
}
448448

449+
// DiscardNext read and discard the data represented by the next line.
450+
func (r *Reader) DiscardNext() error {
451+
line, err := r.readLine()
452+
if err != nil {
453+
return err
454+
}
455+
return r.Discard(line)
456+
}
457+
449458
// Discard the data represented by line.
450459
func (r *Reader) Discard(line []byte) (err error) {
451460
if len(line) == 0 {
@@ -486,15 +495,6 @@ func (r *Reader) Discard(line []byte) (err error) {
486495
return fmt.Errorf("redis: can't parse %.100q", line)
487496
}
488497

489-
// DiscardNext read and discard the data represented by the next line.
490-
func (r *Reader) DiscardNext() error {
491-
line, err := r.readLine()
492-
if err != nil {
493-
return err
494-
}
495-
return r.Discard(line)
496-
}
497-
498498
func replyLen(line []byte) (n int, err error) {
499499
n, err = util.Atoi(line[1:])
500500
if err != nil {
@@ -515,7 +515,7 @@ func replyLen(line []byte) (n int, err error) {
515515
return n, nil
516516
}
517517

518-
// IsNilReply detect redis.Nil of RESP2.
518+
// IsNilReply detects redis.Nil of RESP2.
519519
func IsNilReply(line []byte) bool {
520520
return len(line) == 3 &&
521521
(line[0] == RespString || line[0] == RespArray) &&

redis.go

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -223,13 +223,6 @@ func (c *baseClient) initConn(ctx context.Context, cn *pool.Conn) error {
223223
username, password = c.opt.CredentialsProvider()
224224
}
225225

226-
if password == "" &&
227-
c.opt.DB == 0 &&
228-
!c.opt.readOnly &&
229-
c.opt.OnConnect == nil {
230-
return nil
231-
}
232-
233226
connPool := pool.NewSingleConnPool(c.connPool, cn)
234227
conn := newConn(ctx, c.opt, connPool)
235228

@@ -238,7 +231,7 @@ func (c *baseClient) initConn(ctx context.Context, cn *pool.Conn) error {
238231
// The low version of redis-server does not support the hello command.
239232
// For redis-server (<6.0) that does not support the Hello command,
240233
// we continue to provide services with RESP2.
241-
if err := conn.Hello(ctx, 3, c.opt.Username, c.opt.Password, "").Err(); err == nil {
234+
if err := conn.Hello(ctx, 3, username, password, "").Err(); err == nil {
242235
auth = true
243236
} else if err.Error() != "ERR unknown command 'hello'" {
244237
return err
@@ -514,11 +507,12 @@ func wrapMultiExec(ctx context.Context, cmds []Cmder) []Cmder {
514507
}
515508

516509
func txPipelineReadQueued(rd *proto.Reader, statusCmd *StatusCmd, cmds []Cmder) error {
517-
// Parse queued replies.
510+
// Parse +OK.
518511
if err := statusCmd.readReply(rd); err != nil {
519512
return err
520513
}
521514

515+
// Parse +QUEUED.
522516
for range cmds {
523517
if err := statusCmd.readReply(rd); err != nil && !isRedisError(err) {
524518
return err

0 commit comments

Comments
 (0)