diff options
Diffstat (limited to 'vendor/github.com/go-redis')
10 files changed, 291 insertions, 40 deletions
diff --git a/vendor/github.com/go-redis/redis/v8/Makefile b/vendor/github.com/go-redis/redis/v8/Makefile index d5d5d1900f..348277c07a 100644 --- a/vendor/github.com/go-redis/redis/v8/Makefile +++ b/vendor/github.com/go-redis/redis/v8/Makefile @@ -15,7 +15,7 @@ bench: testdeps testdata/redis: mkdir -p $@ - wget -qO- http://download.redis.io/redis-stable.tar.gz | tar xvz --strip-components=1 -C $@ + wget -qO- https://download.redis.io/releases/redis-6.2-rc3.tar.gz | tar xvz --strip-components=1 -C $@ testdata/redis/src/redis-server: testdata/redis cd $< && make all diff --git a/vendor/github.com/go-redis/redis/v8/command.go b/vendor/github.com/go-redis/redis/v8/command.go index 2932035e72..6ca06344b7 100644 --- a/vendor/github.com/go-redis/redis/v8/command.go +++ b/vendor/github.com/go-redis/redis/v8/command.go @@ -1445,6 +1445,103 @@ func (cmd *XPendingExtCmd) readReply(rd *proto.Reader) error { //------------------------------------------------------------------------------ +type XInfoConsumersCmd struct { + baseCmd + val []XInfoConsumer +} + +type XInfoConsumer struct { + Name string + Pending int64 + Idle int64 +} + +var _ Cmder = (*XInfoGroupsCmd)(nil) + +func NewXInfoConsumersCmd(ctx context.Context, stream string, group string) *XInfoConsumersCmd { + return &XInfoConsumersCmd{ + baseCmd: baseCmd{ + ctx: ctx, + args: []interface{}{"xinfo", "consumers", stream, group}, + }, + } +} + +func (cmd *XInfoConsumersCmd) Val() []XInfoConsumer { + return cmd.val +} + +func (cmd *XInfoConsumersCmd) Result() ([]XInfoConsumer, error) { + return cmd.val, cmd.err +} + +func (cmd *XInfoConsumersCmd) String() string { + return cmdString(cmd, cmd.val) +} + +func (cmd *XInfoConsumersCmd) readReply(rd *proto.Reader) error { + n, err := rd.ReadArrayLen() + if err != nil { + return err + } + + cmd.val = make([]XInfoConsumer, n) + + for i := 0; i < n; i++ { + cmd.val[i], err = readXConsumerInfo(rd) + if err != nil { + return err + } + } + + return nil +} + +func readXConsumerInfo(rd *proto.Reader) (XInfoConsumer, error) { + var consumer XInfoConsumer + + n, err := rd.ReadArrayLen() + if err != nil { + return consumer, err + } + if n != 6 { + return consumer, fmt.Errorf("redis: got %d elements in XINFO CONSUMERS reply, wanted 6", n) + } + + for i := 0; i < 3; i++ { + key, err := rd.ReadString() + if err != nil { + return consumer, err + } + + val, err := rd.ReadString() + if err != nil { + return consumer, err + } + + switch key { + case "name": + consumer.Name = val + case "pending": + consumer.Pending, err = strconv.ParseInt(val, 0, 64) + if err != nil { + return consumer, err + } + case "idle": + consumer.Idle, err = strconv.ParseInt(val, 0, 64) + if err != nil { + return consumer, err + } + default: + return consumer, fmt.Errorf("redis: unexpected content %s in XINFO CONSUMERS reply", key) + } + } + + return consumer, nil +} + +//------------------------------------------------------------------------------ + type XInfoGroupsCmd struct { baseCmd val []XInfoGroup diff --git a/vendor/github.com/go-redis/redis/v8/commands.go b/vendor/github.com/go-redis/redis/v8/commands.go index 422a7c5be2..60f06842fc 100644 --- a/vendor/github.com/go-redis/redis/v8/commands.go +++ b/vendor/github.com/go-redis/redis/v8/commands.go @@ -788,6 +788,56 @@ func (c cmdable) Set(ctx context.Context, key string, value interface{}, expirat return cmd } +// SetArgs provides arguments for the SetArgs function. +type SetArgs struct { + // Mode can be `NX` or `XX` or empty. + Mode string + + // Zero `TTL` or `Expiration` means that the key has no expiration time. + TTL time.Duration + ExpireAt time.Time + + // When Get is true, the command returns the old value stored at key, or nil when key did not exist. + Get bool + + // KeepTTL is a Redis KEEPTTL option to keep existing TTL. + KeepTTL bool +} + +// SetArgs supports all the options that the SET command supports. +// It is the alternative to the Set function when you want +// to have more control over the options. +func (c cmdable) SetArgs(ctx context.Context, key string, value interface{}, a SetArgs) *StatusCmd { + args := []interface{}{"set", key, value} + + if a.KeepTTL { + args = append(args, "keepttl") + } + + if !a.ExpireAt.IsZero() { + args = append(args, "exat", a.ExpireAt.Unix()) + } + if a.TTL > 0 { + if usePrecise(a.TTL) { + args = append(args, "px", formatMs(ctx, a.TTL)) + } else { + args = append(args, "ex", formatSec(ctx, a.TTL)) + } + } + + if a.Mode != "" { + args = append(args, a.Mode) + } + + if a.Get { + args = append(args, "get") + } + + cmd := NewStatusCmd(ctx, args...) + _ = c(ctx, cmd) + return cmd +} + // Redis `SETEX key expiration value` command. func (c cmdable) SetEX(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd { cmd := NewStatusCmd(ctx, "setex", key, formatSec(ctx, expiration), value) @@ -1752,6 +1802,12 @@ func (c cmdable) XTrimApprox(ctx context.Context, key string, maxLen int64) *Int return cmd } +func (c cmdable) XInfoConsumers(ctx context.Context, key string, group string) *XInfoConsumersCmd { + cmd := NewXInfoConsumersCmd(ctx, key, group) + _ = c(ctx, cmd) + return cmd +} + func (c cmdable) XInfoGroups(ctx context.Context, key string) *XInfoGroupsCmd { cmd := NewXInfoGroupsCmd(ctx, key) _ = c(ctx, cmd) diff --git a/vendor/github.com/go-redis/redis/v8/go.mod b/vendor/github.com/go-redis/redis/v8/go.mod index 4f5952762f..29182d266c 100644 --- a/vendor/github.com/go-redis/redis/v8/go.mod +++ b/vendor/github.com/go-redis/redis/v8/go.mod @@ -7,5 +7,7 @@ require ( github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f github.com/onsi/ginkgo v1.15.0 github.com/onsi/gomega v1.10.5 - go.opentelemetry.io/otel v0.16.0 + go.opentelemetry.io/otel v0.17.0 + go.opentelemetry.io/otel/metric v0.17.0 + go.opentelemetry.io/otel/trace v0.17.0 ) diff --git a/vendor/github.com/go-redis/redis/v8/go.sum b/vendor/github.com/go-redis/redis/v8/go.sum index b46929e693..9532f045af 100644 --- a/vendor/github.com/go-redis/redis/v8/go.sum +++ b/vendor/github.com/go-redis/redis/v8/go.sum @@ -25,22 +25,26 @@ github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M= -github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.15.0 h1:1V1NfVQR87RtWAgp1lv9JZJ5Jap+XFGKPi00andXGi4= github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.10.4 h1:NiTx7EEvBzu9sFOD1zORteLSt3o8gnlvZZwSE9TnY9U= -github.com/onsi/gomega v1.10.4/go.mod h1:g/HbgYopi++010VEqkFgJHKC09uJiW9UkXvMUuKHUCQ= +github.com/onsi/gomega v1.10.5 h1:7n6FEkpFmfCoo2t+YYqXH0evK+a9ICQz0xcAy9dYcaQ= github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v0.16.0 h1:uIWEbdeb4vpKPGITLsRVUS44L5oDbDUCZxn8lkxhmgw= -go.opentelemetry.io/otel v0.16.0/go.mod h1:e4GKElweB8W2gWUqbghw0B8t5MCTccc9212eNHnOHwA= +go.opentelemetry.io/otel v0.17.0 h1:6MKOu8WY4hmfpQ4oQn34u6rYhnf2sWf1LXYO/UFm71U= +go.opentelemetry.io/otel v0.17.0/go.mod h1:Oqtdxmf7UtEvL037ohlgnaYa1h7GtMh0NcSd9eqkC9s= +go.opentelemetry.io/otel/metric v0.17.0 h1:t+5EioN8YFXQ2EH+1j6FHCKMUj+57zIDSnSGr/mWuug= +go.opentelemetry.io/otel/metric v0.17.0/go.mod h1:hUz9lH1rNXyEwWAhIWCMFWKhYtpASgSnObJFnU26dJ0= +go.opentelemetry.io/otel/oteltest v0.17.0 h1:TyAihUowTDLqb4+m5ePAsR71xPJaTBJl4KDArIdi9k4= +go.opentelemetry.io/otel/oteltest v0.17.0/go.mod h1:JT/LGFxPwpN+nlsTiinSYjdIx3hZIGqHCpChcIZmdoE= +go.opentelemetry.io/otel/trace v0.17.0 h1:SBOj64/GAOyWzs5F680yW1ITIfJkm6cJWL2YAvuL9xY= +go.opentelemetry.io/otel/trace v0.17.0/go.mod h1:bIujpqg6ZL6xUTubIUgziI1jSaUPthmabA/ygf/6Cfg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -62,12 +66,10 @@ golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091 h1:DMyOG0U+gKfu8JZzg2UQe9MeaC1X+xQWlAKcRnjxjCw= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -75,8 +77,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= diff --git a/vendor/github.com/go-redis/redis/v8/internal/hscan/hscan.go b/vendor/github.com/go-redis/redis/v8/internal/hscan/hscan.go index 181260b802..6f97f9287c 100644 --- a/vendor/github.com/go-redis/redis/v8/internal/hscan/hscan.go +++ b/vendor/github.com/go-redis/redis/v8/internal/hscan/hscan.go @@ -15,17 +15,17 @@ var ( decoders = []decoderFunc{ reflect.Bool: decodeBool, reflect.Int: decodeInt, - reflect.Int8: decodeInt, - reflect.Int16: decodeInt, - reflect.Int32: decodeInt, - reflect.Int64: decodeInt, + reflect.Int8: decodeInt8, + reflect.Int16: decodeInt16, + reflect.Int32: decodeInt32, + reflect.Int64: decodeInt64, reflect.Uint: decodeUint, - reflect.Uint8: decodeUint, - reflect.Uint16: decodeUint, - reflect.Uint32: decodeUint, - reflect.Uint64: decodeUint, - reflect.Float32: decodeFloat, - reflect.Float64: decodeFloat, + reflect.Uint8: decodeUint8, + reflect.Uint16: decodeUint16, + reflect.Uint32: decodeUint32, + reflect.Uint64: decodeUint64, + reflect.Float32: decodeFloat32, + reflect.Float64: decodeFloat64, reflect.Complex64: decodeUnsupported, reflect.Complex128: decodeUnsupported, reflect.Array: decodeUnsupported, @@ -106,8 +106,28 @@ func decodeBool(f reflect.Value, s string) error { return nil } +func decodeInt8(f reflect.Value, s string) error { + return decodeNumber(f, s, 8) +} + +func decodeInt16(f reflect.Value, s string) error { + return decodeNumber(f, s, 16) +} + +func decodeInt32(f reflect.Value, s string) error { + return decodeNumber(f, s, 32) +} + +func decodeInt64(f reflect.Value, s string) error { + return decodeNumber(f, s, 64) +} + func decodeInt(f reflect.Value, s string) error { - v, err := strconv.ParseInt(s, 10, 0) + return decodeNumber(f, s, 0) +} + +func decodeNumber(f reflect.Value, s string, bitSize int) error { + v, err := strconv.ParseInt(s, 10, bitSize) if err != nil { return err } @@ -115,8 +135,28 @@ func decodeInt(f reflect.Value, s string) error { return nil } +func decodeUint8(f reflect.Value, s string) error { + return decodeUnsignedNumber(f, s, 8) +} + +func decodeUint16(f reflect.Value, s string) error { + return decodeUnsignedNumber(f, s, 16) +} + +func decodeUint32(f reflect.Value, s string) error { + return decodeUnsignedNumber(f, s, 32) +} + +func decodeUint64(f reflect.Value, s string) error { + return decodeUnsignedNumber(f, s, 64) +} + func decodeUint(f reflect.Value, s string) error { - v, err := strconv.ParseUint(s, 10, 0) + return decodeUnsignedNumber(f, s, 0) +} + +func decodeUnsignedNumber(f reflect.Value, s string, bitSize int) error { + v, err := strconv.ParseUint(s, 10, bitSize) if err != nil { return err } @@ -124,8 +164,18 @@ func decodeUint(f reflect.Value, s string) error { return nil } -func decodeFloat(f reflect.Value, s string) error { - v, err := strconv.ParseFloat(s, 0) +func decodeFloat32(f reflect.Value, s string) error { + v, err := strconv.ParseFloat(s, 32) + if err != nil { + return err + } + f.SetFloat(v) + return nil +} + +// although the default is float64, but we better define it. +func decodeFloat64(f reflect.Value, s string) error { + v, err := strconv.ParseFloat(s, 64) if err != nil { return err } diff --git a/vendor/github.com/go-redis/redis/v8/internal/hscan/structmap.go b/vendor/github.com/go-redis/redis/v8/internal/hscan/structmap.go index 37d86ba551..1b233258df 100644 --- a/vendor/github.com/go-redis/redis/v8/internal/hscan/structmap.go +++ b/vendor/github.com/go-redis/redis/v8/internal/hscan/structmap.go @@ -1,6 +1,7 @@ package hscan import ( + "fmt" "reflect" "strings" "sync" @@ -83,5 +84,10 @@ func (s StructValue) Scan(key string, value string) error { if !ok { return nil } - return field.fn(s.value.Field(field.index), value) + if err := field.fn(s.value.Field(field.index), value); err != nil { + t := s.value.Type() + return fmt.Errorf("cannot scan redis.result %s into struct field %s.%s of type %s, error-%s", + value, t.Name(), t.Field(field.index).Name, t.Field(field.index).Type, err.Error()) + } + return nil } diff --git a/vendor/github.com/go-redis/redis/v8/internal/instruments.go b/vendor/github.com/go-redis/redis/v8/internal/instruments.go index 2d7dacce7a..49d6111e18 100644 --- a/vendor/github.com/go-redis/redis/v8/internal/instruments.go +++ b/vendor/github.com/go-redis/redis/v8/internal/instruments.go @@ -3,8 +3,8 @@ package internal import ( "context" - "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/metric/global" ) var ( @@ -21,7 +21,7 @@ func init() { } }() - meter := metric.Must(otel.Meter("github.com/go-redis/redis")) + meter := metric.Must(global.Meter("github.com/go-redis/redis")) WritesCounter = meter.NewInt64Counter("redis.writes", metric.WithDescription("the number of writes initiated"), diff --git a/vendor/github.com/go-redis/redis/v8/internal/rand/rand.go b/vendor/github.com/go-redis/redis/v8/internal/rand/rand.go index 40676f3cb6..2edccba94f 100644 --- a/vendor/github.com/go-redis/redis/v8/internal/rand/rand.go +++ b/vendor/github.com/go-redis/redis/v8/internal/rand/rand.go @@ -43,3 +43,8 @@ func (s *source) Seed(seed int64) { s.src.Seed(seed) s.mu.Unlock() } + +// Shuffle pseudo-randomizes the order of elements. +// n is the number of elements. +// swap swaps the elements with indexes i and j. +func Shuffle(n int, swap func(i, j int)) { pseudo.Shuffle(n, swap) } diff --git a/vendor/github.com/go-redis/redis/v8/sentinel.go b/vendor/github.com/go-redis/redis/v8/sentinel.go index d785168ff1..3e8afb7458 100644 --- a/vendor/github.com/go-redis/redis/v8/sentinel.go +++ b/vendor/github.com/go-redis/redis/v8/sentinel.go @@ -36,6 +36,12 @@ type FailoverOptions struct { // Route all commands to slave read-only nodes. SlaveOnly bool + // Use slaves disconnected with master when cannot get connected slaves + // Now, this option only works in RandomSlaveAddr function. + UseDisconnectedSlaves bool + + // Client queries sentinels in a random order + QuerySentinelRandomly bool // Following options are copied from Options struct. Dialer func(ctx context.Context, network, addr string) (net.Conn, error) @@ -167,6 +173,10 @@ func NewFailoverClient(failoverOpt *FailoverOptions) *Client { sentinelAddrs := make([]string, len(failoverOpt.SentinelAddrs)) copy(sentinelAddrs, failoverOpt.SentinelAddrs) + rand.Shuffle(len(sentinelAddrs), func(i, j int) { + sentinelAddrs[i], sentinelAddrs[j] = sentinelAddrs[j], sentinelAddrs[i] + }) + failover := &sentinelFailover{ opt: failoverOpt, sentinelAddrs: sentinelAddrs, @@ -433,10 +443,22 @@ func (c *sentinelFailover) closeSentinel() error { } func (c *sentinelFailover) RandomSlaveAddr(ctx context.Context) (string, error) { - addresses, err := c.slaveAddrs(ctx) + if c.opt == nil { + return "", errors.New("opt is nil") + } + + addresses, err := c.slaveAddrs(ctx, false) if err != nil { return "", err } + + if len(addresses) == 0 && c.opt.UseDisconnectedSlaves { + addresses, err = c.slaveAddrs(ctx, true) + if err != nil { + return "", err + } + } + if len(addresses) == 0 { return c.MasterAddr(ctx) } @@ -488,7 +510,7 @@ func (c *sentinelFailover) MasterAddr(ctx context.Context) (string, error) { return "", errors.New("redis: all sentinels specified in configuration are unreachable") } -func (c *sentinelFailover) slaveAddrs(ctx context.Context) ([]string, error) { +func (c *sentinelFailover) slaveAddrs(ctx context.Context, useDisconnected bool) ([]string, error) { c.mu.RLock() sentinel := c.sentinel c.mu.RUnlock() @@ -511,6 +533,8 @@ func (c *sentinelFailover) slaveAddrs(ctx context.Context) ([]string, error) { _ = c.closeSentinel() } + var sentinelReachable bool + for i, sentinelAddr := range c.sentinelAddrs { sentinel := NewSentinelClient(c.opt.sentinelOptions(sentinelAddr)) @@ -521,15 +545,21 @@ func (c *sentinelFailover) slaveAddrs(ctx context.Context) ([]string, error) { _ = sentinel.Close() continue } - + sentinelReachable = true + addrs := parseSlaveAddrs(slaves, useDisconnected) + if len(addrs) == 0 { + continue + } // Push working sentinel to the top. c.sentinelAddrs[0], c.sentinelAddrs[i] = c.sentinelAddrs[i], c.sentinelAddrs[0] c.setSentinel(ctx, sentinel) - addrs := parseSlaveAddrs(slaves) return addrs, nil } + if sentinelReachable { + return []string{}, nil + } return []string{}, errors.New("redis: all sentinels specified in configuration are unreachable") } @@ -550,12 +580,11 @@ func (c *sentinelFailover) getSlaveAddrs(ctx context.Context, sentinel *Sentinel c.opt.MasterName, err) return []string{} } - return parseSlaveAddrs(addrs) + return parseSlaveAddrs(addrs, false) } -func parseSlaveAddrs(addrs []interface{}) []string { +func parseSlaveAddrs(addrs []interface{}, keepDisconnected bool) []string { nodes := make([]string, 0, len(addrs)) - for _, node := range addrs { ip := "" port := "" @@ -577,8 +606,12 @@ func parseSlaveAddrs(addrs []interface{}) []string { for _, flag := range flags { switch flag { - case "s_down", "o_down", "disconnected": + case "s_down", "o_down": isDown = true + case "disconnected": + if !keepDisconnected { + isDown = true + } } } @@ -705,7 +738,7 @@ func NewFailoverClusterClient(failoverOpt *FailoverOptions) *ClusterClient { Addr: masterAddr, }} - slaveAddrs, err := failover.slaveAddrs(ctx) + slaveAddrs, err := failover.slaveAddrs(ctx, false) if err != nil { return nil, err } |