From 26a6d4714c4e5c0d310ca752e6f65c00eac20b4c Mon Sep 17 00:00:00 2001 From: Scott Parkerson Date: Thu, 17 Sep 2020 10:35:34 -0400 Subject: [PATCH] Fixes #1386; pipeline.Exec() sometimes returns spurious `StatusCmd` This is caused by function `wrapMultiExec` sometimes clobbering the caller's cmd slice, corrupting future requests. --- pipeline_test.go | 17 +++++++++++++++++ redis.go | 10 +++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/pipeline_test.go b/pipeline_test.go index 3a767f8d..9d2a60cf 100644 --- a/pipeline_test.go +++ b/pipeline_test.go @@ -1,6 +1,8 @@ package redis_test import ( + "strconv" + "github.com/go-redis/redis/v8" . "github.com/onsi/ginkgo" @@ -67,6 +69,21 @@ var _ = Describe("pipelining", func() { Expect(err).NotTo(HaveOccurred()) Expect(cmds).To(HaveLen(1)) }) + + It("handles large pipelines", func() { + for callCount := 1; callCount < 16; callCount++ { + for i := 1; i <= callCount; i++ { + pipe.SetNX(ctx, strconv.Itoa(i)+"_key", strconv.Itoa(i)+"_value", 0) + } + + cmds, err := pipe.Exec(ctx) + Expect(err).NotTo(HaveOccurred()) + Expect(cmds).To(HaveLen(callCount)) + for _, cmd := range cmds { + Expect(cmd).To(BeAssignableToTypeOf(&redis.BoolCmd{})) + } + } + }) } Describe("Pipeline", func() { diff --git a/redis.go b/redis.go index 0921359e..3cff1b5e 100644 --- a/redis.go +++ b/redis.go @@ -492,11 +492,11 @@ func wrapMultiExec(ctx context.Context, cmds []Cmder) []Cmder { if len(cmds) == 0 { panic("not reached") } - cmds = append(cmds, make([]Cmder, 2)...) - copy(cmds[1:], cmds[:len(cmds)-2]) - cmds[0] = NewStatusCmd(ctx, "multi") - cmds[len(cmds)-1] = NewSliceCmd(ctx, "exec") - return cmds + cmdCopy := make([]Cmder, len(cmds)+2) + cmdCopy[0] = NewStatusCmd(ctx, "multi") + copy(cmdCopy[1:], cmds) + cmdCopy[len(cmdCopy)-1] = NewSliceCmd(ctx, "exec") + return cmdCopy } func txPipelineReadQueued(rd *proto.Reader, statusCmd *StatusCmd, cmds []Cmder) error {