Skip to content

Different responses for cmd.Result() in pipelines starting in v9.14.0 #3524

@zhughes3

Description

@zhughes3

Expected Behavior

When running SET in a pipeline, fetching the response with value, err := cmd.Result() used to return a err in <=v9.13.0.

Current Behavior

When running SET in a pipeline, fetching the response with value, err := cmd.Result() returns a redis.Nil error.

Possible Solution

Steps to Reproduce

// This unit test would passes in v9.13.0 but fails in v9.14.0.
package redis

import (
	"testing"
	"time"

	"github.com/alicebob/miniredis/v2"
	"github.com/redis/go-redis/v9"
	"github.com/stretchr/testify/suite"
	"golang.org/x/net/context"
)

type redisDependencyUpdateSuite struct {
	suite.Suite

	redisServer *miniredis.Miniredis
	redisClient *redis.Client

	ctx context.Context
}

func TestRedisDependencyUpdateSuite(t *testing.T) {
	suite.Run(t, new(redisDependencyUpdateSuite))
}

func (s *redisDependencyUpdateSuite) SetupSuite() {
	s.redisServer = miniredis.RunT(s.T())
}

func (s *redisDependencyUpdateSuite) SetupTest() {
	s.redisClient = redis.NewClient(defaultClientOptions(s.redisServer.Addr()))
	s.ctx = context.Background()
}

func (s *redisDependencyUpdateSuite) TearDownTest() {
	s.redisClient.Close()
}

func (s *redisDependencyUpdateSuite) TearDownSuite() {
	s.redisServer.Close()
}

func (s *redisDependencyUpdateSuite) TestPipeline() {
	pipeline := s.redisClient.Pipeline()
	pipeline.Do(s.ctx, "GET", "unittest")
	pipeline.Do(s.ctx, "SET", "unittest", "tested")
	pipeline.Do(s.ctx, "GET", "unittest")

	cmds, err := pipeline.Exec(s.ctx)

	s.Require().Len(cmds, 3)

	// First GET should not be found.
	cmd, ok := cmds[0].(*redis.Cmd)
	s.Require().True(ok)
	val, err := cmd.Result()
	s.Require().Equal(redis.Nil, err)
	s.Require().Nil(val)

	cmd, ok = cmds[1].(*redis.Cmd)
	s.Require().True(ok)

	// v9.14.0 now returns [redis.Nil] for the err
	// v9.13.0 and earlier returned <nil> for the err.
	val, err = cmd.Result()
	s.Require().NoError(err)
	s.Require().Equal("OK", val)

	// Second GET should return the value we just set.
	cmd, ok = cmds[2].(*redis.Cmd)
	s.Require().True(ok)
	val, err = cmd.Result()
	s.Require().NoError(err)
	s.Require().Equal("tested", val)
}

func defaultClientOptions(addr string) *redis.Options {
	return &redis.Options{
		Addr: addr,
		DB:   0,

		DialTimeout:           10 * time.Second,
		ReadTimeout:           30 * time.Second,
		WriteTimeout:          30 * time.Second,
		ContextTimeoutEnabled: true,

		MaxRetries: -1,

		PoolSize:        10,
		PoolTimeout:     30 * time.Second,
		ConnMaxIdleTime: time.Minute,
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions