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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions