From 6e4eb2e3acad9575fb1e2c8690a3c1decf2e59e5 Mon Sep 17 00:00:00 2001 From: Vladimir Mihailenco Date: Thu, 3 Jun 2021 14:01:51 +0300 Subject: [PATCH 01/21] Remove OpenTelemetry from the code (but leave redisotel as is) (#1782) --- CHANGELOG.md | 13 +++++++++++++ go.mod | 2 -- internal/pool/conn.go | 19 +++++-------------- internal/util.go | 24 ------------------------ options.go | 18 +----------------- redis.go | 13 ------------- 6 files changed, 19 insertions(+), 70 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b540a4..42d89b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,19 @@ > :heart: > [**Uptrace.dev** - All-in-one tool to optimize performance and monitor errors & logs](https://uptrace.dev) +## v8.10 + +- Removed extra OpenTelemetry spans from go-redis core. Now go-redis instrumentation only adds a + single span with a Redis command (instead of 4 spans). There are multiple reasons behind this + decision: + + - Traces become smaller and less noisy. + - It may be costly to process those 3 extra spans for each query. + - go-redis no longer depends on OpenTelemetry. + + Eventually we hope to replace the information that we no longer collect with OpenTelemetry + Metrics. + ## v8.9 - Changed `PubSub.Channel` to only rely on `Ping` result. You can now use `WithChannelSize`, diff --git a/go.mod b/go.mod index bfe9148..aa13d2e 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,5 @@ 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.20.0 go.opentelemetry.io/otel/metric v0.20.0 - go.opentelemetry.io/otel/trace v0.20.0 ) diff --git a/internal/pool/conn.go b/internal/pool/conn.go index ee064c9..1ce29ed 100644 --- a/internal/pool/conn.go +++ b/internal/pool/conn.go @@ -65,26 +65,17 @@ func (cn *Conn) RemoteAddr() net.Addr { } func (cn *Conn) WithReader(ctx context.Context, timeout time.Duration, fn func(rd *proto.Reader) error) error { - ctx, span := internal.StartSpan(ctx, "redis.with_reader") - defer span.End() - if err := cn.netConn.SetReadDeadline(cn.deadline(ctx, timeout)); err != nil { - return internal.RecordError(ctx, span, err) + return err } - if err := fn(cn.rd); err != nil { - return internal.RecordError(ctx, span, err) - } - return nil + return fn(cn.rd) } func (cn *Conn) WithWriter( ctx context.Context, timeout time.Duration, fn func(wr *proto.Writer) error, ) error { - ctx, span := internal.StartSpan(ctx, "redis.with_writer") - defer span.End() - if err := cn.netConn.SetWriteDeadline(cn.deadline(ctx, timeout)); err != nil { - return internal.RecordError(ctx, span, err) + return err } if cn.bw.Buffered() > 0 { @@ -92,11 +83,11 @@ func (cn *Conn) WithWriter( } if err := fn(cn.wr); err != nil { - return internal.RecordError(ctx, span, err) + return err } if err := cn.bw.Flush(); err != nil { - return internal.RecordError(ctx, span, err) + return err } internal.WritesCounter.Add(ctx, 1) diff --git a/internal/util.go b/internal/util.go index 1a648fe..e34a7f0 100644 --- a/internal/util.go +++ b/internal/util.go @@ -4,16 +4,10 @@ import ( "context" "time" - "github.com/go-redis/redis/v8/internal/proto" "github.com/go-redis/redis/v8/internal/util" - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/trace" ) func Sleep(ctx context.Context, dur time.Duration) error { - _, span := StartSpan(ctx, "time.Sleep") - defer span.End() - t := time.NewTimer(dur) defer t.Stop() @@ -50,21 +44,3 @@ func isLower(s string) bool { } return true } - -//------------------------------------------------------------------------------ - -var tracer = otel.Tracer("github.com/go-redis/redis") - -func StartSpan(ctx context.Context, name string) (context.Context, trace.Span) { - if span := trace.SpanFromContext(ctx); !span.IsRecording() { - return ctx, span - } - return tracer.Start(ctx, name) -} - -func RecordError(ctx context.Context, span trace.Span, err error) error { - if err != proto.Nil { - span.RecordError(err) - } - return err -} diff --git a/options.go b/options.go index 0fd8e88..7cf1bc1 100644 --- a/options.go +++ b/options.go @@ -12,9 +12,7 @@ import ( "strings" "time" - "github.com/go-redis/redis/v8/internal" "github.com/go-redis/redis/v8/internal/pool" - "go.opentelemetry.io/otel/attribute" ) // Limiter is the interface of a rate limiter or a circuit breaker. @@ -291,21 +289,7 @@ func getUserPassword(u *url.URL) (string, string) { func newConnPool(opt *Options) *pool.ConnPool { return pool.NewConnPool(&pool.Options{ Dialer: func(ctx context.Context) (net.Conn, error) { - ctx, span := internal.StartSpan(ctx, "redis.dial") - defer span.End() - - if span.IsRecording() { - span.SetAttributes( - attribute.String("db.connection_string", opt.Addr), - ) - } - - cn, err := opt.Dialer(ctx, opt.Network, opt.Addr) - if err != nil { - return nil, internal.RecordError(ctx, span, err) - } - - return cn, nil + return opt.Dialer(ctx, opt.Network, opt.Addr) }, PoolSize: opt.PoolSize, MinIdleConns: opt.MinIdleConns, diff --git a/redis.go b/redis.go index 7995c43..98d6034 100644 --- a/redis.go +++ b/redis.go @@ -10,7 +10,6 @@ import ( "github.com/go-redis/redis/v8/internal" "github.com/go-redis/redis/v8/internal/pool" "github.com/go-redis/redis/v8/internal/proto" - "go.opentelemetry.io/otel/attribute" ) // Nil reply returned by Redis when key does not exist. @@ -237,9 +236,6 @@ func (c *baseClient) initConn(ctx context.Context, cn *pool.Conn) error { return nil } - ctx, span := internal.StartSpan(ctx, "redis.init_conn") - defer span.End() - connPool := pool.NewSingleConnPool(c.connPool, cn) conn := newConn(ctx, c.opt, connPool) @@ -287,20 +283,11 @@ func (c *baseClient) releaseConn(ctx context.Context, cn *pool.Conn, err error) func (c *baseClient) withConn( ctx context.Context, fn func(context.Context, *pool.Conn) error, ) error { - ctx, span := internal.StartSpan(ctx, "redis.with_conn") - defer span.End() - cn, err := c.getConn(ctx) if err != nil { return err } - if span.IsRecording() { - if remoteAddr := cn.RemoteAddr(); remoteAddr != nil { - span.SetAttributes(attribute.String("net.peer.ip", remoteAddr.String())) - } - } - defer func() { c.releaseConn(ctx, cn, err) }() From 237bad52843904773090adc08ba660050b9f2e80 Mon Sep 17 00:00:00 2001 From: ericmillin <31105612+ericmillin@users.noreply.github.com> Date: Fri, 4 Jun 2021 11:04:36 -0400 Subject: [PATCH 02/21] Add XAutoClaim command (#1780) --- command.go | 116 +++++++++++++++++++++++++++++++++++++++++++++++ commands.go | 33 ++++++++++++++ commands_test.go | 37 +++++++++++++++ 3 files changed, 186 insertions(+) diff --git a/command.go b/command.go index 9a3018d..77d0bad 100644 --- a/command.go +++ b/command.go @@ -1501,6 +1501,122 @@ func (cmd *XPendingExtCmd) readReply(rd *proto.Reader) error { //------------------------------------------------------------------------------ +type XAutoClaimCmd struct { + baseCmd + + start string + val []XMessage +} + +var _ Cmder = (*XAutoClaimCmd)(nil) + +func NewXAutoClaimCmd(ctx context.Context, args ...interface{}) *XAutoClaimCmd { + return &XAutoClaimCmd{ + baseCmd: baseCmd{ + ctx: ctx, + args: args, + }, + } +} + +func (cmd *XAutoClaimCmd) Val() (messages []XMessage, start string) { + return cmd.val, cmd.start +} + +func (cmd *XAutoClaimCmd) Result() (messages []XMessage, start string, err error) { + return cmd.val, cmd.start, cmd.err +} + +func (cmd *XAutoClaimCmd) String() string { + return cmdString(cmd, cmd.val) +} + +func (cmd *XAutoClaimCmd) readReply(rd *proto.Reader) error { + _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) { + if n != 2 { + return nil, fmt.Errorf("got %d, wanted 2", n) + } + var err error + + cmd.start, err = rd.ReadString() + if err != nil { + return nil, err + } + + cmd.val, err = readXMessageSlice(rd) + if err != nil { + return nil, err + } + + return nil, nil + }) + return err +} + +//------------------------------------------------------------------------------ + +type XAutoClaimJustIDCmd struct { + baseCmd + + start string + val []string +} + +var _ Cmder = (*XAutoClaimJustIDCmd)(nil) + +func NewXAutoClaimJustIDCmd(ctx context.Context, args ...interface{}) *XAutoClaimJustIDCmd { + return &XAutoClaimJustIDCmd{ + baseCmd: baseCmd{ + ctx: ctx, + args: args, + }, + } +} + +func (cmd *XAutoClaimJustIDCmd) Val() (ids []string, start string) { + return cmd.val, cmd.start +} + +func (cmd *XAutoClaimJustIDCmd) Result() (ids []string, start string, err error) { + return cmd.val, cmd.start, cmd.err +} + +func (cmd *XAutoClaimJustIDCmd) String() string { + return cmdString(cmd, cmd.val) +} + +func (cmd *XAutoClaimJustIDCmd) readReply(rd *proto.Reader) error { + _, err := rd.ReadArrayReply(func(rd *proto.Reader, n int64) (interface{}, error) { + if n != 2 { + return nil, fmt.Errorf("got %d, wanted 2", n) + } + var err error + + cmd.start, err = rd.ReadString() + if err != nil { + return nil, err + } + + nn, err := rd.ReadArrayLen() + if err != nil { + return nil, err + } + + cmd.val = make([]string, nn) + for i := 0; i < nn; i++ { + cmd.val[i], err = rd.ReadString() + if err != nil { + return nil, err + } + } + + return nil, nil + }) + return err +} + +//------------------------------------------------------------------------------ + type XInfoConsumersCmd struct { baseCmd val []XInfoConsumer diff --git a/commands.go b/commands.go index 4ac42ec..b3b15c7 100644 --- a/commands.go +++ b/commands.go @@ -1845,6 +1845,39 @@ func (c cmdable) XPendingExt(ctx context.Context, a *XPendingExtArgs) *XPendingE return cmd } +type XAutoClaimArgs struct { + Stream string + Group string + MinIdle time.Duration + Start string + Count int64 + Consumer string +} + +func (c cmdable) XAutoClaim(ctx context.Context, a *XAutoClaimArgs) *XAutoClaimCmd { + args := xAutoClaimArgs(ctx, a) + cmd := NewXAutoClaimCmd(ctx, args...) + _ = c(ctx, cmd) + return cmd +} + +func (c cmdable) XAutoClaimJustID(ctx context.Context, a *XAutoClaimArgs) *XAutoClaimJustIDCmd { + args := xAutoClaimArgs(ctx, a) + args = append(args, "justid") + cmd := NewXAutoClaimJustIDCmd(ctx, args...) + _ = c(ctx, cmd) + return cmd +} + +func xAutoClaimArgs(ctx context.Context, a *XAutoClaimArgs) []interface{} { + args := make([]interface{}, 0, 9) + args = append(args, "xautoclaim", a.Stream, a.Group, a.Consumer, formatMs(ctx, a.MinIdle), a.Start) + if a.Count > 0 { + args = append(args, "count", a.Count) + } + return args +} + type XClaimArgs struct { Stream string Group string diff --git a/commands_test.go b/commands_test.go index 427fec7..11b8592 100644 --- a/commands_test.go +++ b/commands_test.go @@ -4386,6 +4386,43 @@ var _ = Describe("Commands", func() { Expect(n).To(Equal(int64(3))) }) + It("should XAutoClaim", func() { + xca := &redis.XAutoClaimArgs{ + Stream: "stream", + Group: "group", + Consumer: "consumer", + Start: "-", + Count: 2, + } + msgs, start, err := client.XAutoClaim(ctx, xca).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(start).To(Equal("2-0")) + Expect(msgs).To(Equal([]redis.XMessage{{ + ID: "1-0", + Values: map[string]interface{}{"uno": "un"}, + }, { + ID: "2-0", + Values: map[string]interface{}{"dos": "deux"}, + }})) + + xca.Start = start + msgs, start, err = client.XAutoClaim(ctx, xca).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(start).To(Equal("3-0")) + Expect(msgs).To(Equal([]redis.XMessage{{ + ID: "2-0", + Values: map[string]interface{}{"dos": "deux"}, + }, { + ID: "3-0", + Values: map[string]interface{}{"tres": "troix"}, + }})) + + ids, start, err := client.XAutoClaimJustID(ctx, xca).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(start).To(Equal("3-0")) + Expect(ids).To(Equal([]string{"2-0", "3-0"})) + }) + It("should XClaim", func() { msgs, err := client.XClaim(ctx, &redis.XClaimArgs{ Stream: "stream", From 14d82a2d93fccea4124fc8d6cc0fdc45285a878c Mon Sep 17 00:00:00 2001 From: heyanfu <1145291570@qq.com> Date: Wed, 9 Jun 2021 00:58:16 +0800 Subject: [PATCH 03/21] fix typo (#1788) --- internal/hscan/hscan.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/hscan/hscan.go b/internal/hscan/hscan.go index 6f97f92..852c8bd 100644 --- a/internal/hscan/hscan.go +++ b/internal/hscan/hscan.go @@ -49,7 +49,7 @@ var ( func Struct(dst interface{}) (StructValue, error) { v := reflect.ValueOf(dst) - // The dstination to scan into should be a struct pointer. + // The destination to scan into should be a struct pointer. if v.Kind() != reflect.Ptr || v.IsNil() { return StructValue{}, fmt.Errorf("redis.Scan(non-pointer %T)", dst) } From 43ec1464d9a6b61419090f07a2e49b66bfb0d85b Mon Sep 17 00:00:00 2001 From: monkey92t Date: Tue, 15 Jun 2021 16:48:35 +0800 Subject: [PATCH 04/21] xgroup/xadd/xtrim supports new options (#1787) * support cmd option XGROUP CREATECONSUMER XTRIM MINID LIMIT XADD NOMKSTREAM MINID LIMIT Signed-off-by: monkey * add XAddArgs.Approx doc Signed-off-by: monkey92t --- commands.go | 118 +++++++++++++++++++++++++++++++++++++++++------ commands_test.go | 55 +++++++++++++++++++++- 2 files changed, 157 insertions(+), 16 deletions(-) diff --git a/commands.go b/commands.go index b3b15c7..32f954e 100644 --- a/commands.go +++ b/commands.go @@ -226,6 +226,7 @@ type Cmdable interface { XGroupCreateMkStream(ctx context.Context, stream, group, start string) *StatusCmd XGroupSetID(ctx context.Context, stream, group, start string) *StatusCmd XGroupDestroy(ctx context.Context, stream, group string) *IntCmd + XGroupCreateConsumer(ctx context.Context, stream, group, consumer string) *IntCmd XGroupDelConsumer(ctx context.Context, stream, group, consumer string) *IntCmd XReadGroup(ctx context.Context, a *XReadGroupArgs) *XStreamSliceCmd XAck(ctx context.Context, stream, group string, ids ...string) *IntCmd @@ -233,8 +234,14 @@ type Cmdable interface { XPendingExt(ctx context.Context, a *XPendingExtArgs) *XPendingExtCmd XClaim(ctx context.Context, a *XClaimArgs) *XMessageSliceCmd XClaimJustID(ctx context.Context, a *XClaimArgs) *StringSliceCmd + + // TODO: XTrim and XTrimApprox remove in v9. XTrim(ctx context.Context, key string, maxLen int64) *IntCmd XTrimApprox(ctx context.Context, key string, maxLen int64) *IntCmd + XTrimMaxLen(ctx context.Context, key string, maxLen int64) *IntCmd + XTrimMaxLenApprox(ctx context.Context, key string, maxLen, limit int64) *IntCmd + XTrimMinID(ctx context.Context, key string, minID string) *IntCmd + XTrimMinIDApprox(ctx context.Context, key string, minID string, limit int64) *IntCmd XInfoGroups(ctx context.Context, key string) *XInfoGroupsCmd XInfoStream(ctx context.Context, key string) *XInfoStreamCmd XInfoConsumers(ctx context.Context, key string, group string) *XInfoConsumersCmd @@ -1621,22 +1628,50 @@ func (c cmdable) SUnionStore(ctx context.Context, destination string, keys ...st // - XAddArgs.Values = map[string]interface{}{"key1": "value1", "key2": "value2"} // // Note that map will not preserve the order of key-value pairs. +// MaxLen/MaxLenApprox and MinID are in conflict, only one of them can be used. type XAddArgs struct { - Stream string - MaxLen int64 // MAXLEN N + Stream string + NoMkStream bool + MaxLen int64 // MAXLEN N + + // Deprecated: use MaxLen+Approx, remove in v9. MaxLenApprox int64 // MAXLEN ~ N - ID string - Values interface{} + + MinID string + // Approx causes MaxLen and MinID to use "~" matcher (instead of "="). + Approx bool + Limit int64 + ID string + Values interface{} } +// XAdd a.Limit has a bug, please confirm it and use it. +// issue: https://github.com/redis/redis/issues/9046 func (c cmdable) XAdd(ctx context.Context, a *XAddArgs) *StringCmd { - args := make([]interface{}, 0, 8) - args = append(args, "xadd") - args = append(args, a.Stream) - if a.MaxLen > 0 { - args = append(args, "maxlen", a.MaxLen) - } else if a.MaxLenApprox > 0 { + args := make([]interface{}, 0, 11) + args = append(args, "xadd", a.Stream) + if a.NoMkStream { + args = append(args, "nomkstream") + } + switch { + case a.MaxLen > 0: + if a.Approx { + args = append(args, "maxlen", "~", a.MaxLen) + } else { + args = append(args, "maxlen", a.MaxLen) + } + case a.MaxLenApprox > 0: + // TODO remove in v9. args = append(args, "maxlen", "~", a.MaxLenApprox) + case a.MinID != "": + if a.Approx { + args = append(args, "minid", "~", a.MinID) + } else { + args = append(args, "minid", a.MinID) + } + } + if a.Limit > 0 { + args = append(args, "limit", a.Limit) } if a.ID != "" { args = append(args, a.ID) @@ -1757,6 +1792,12 @@ func (c cmdable) XGroupDestroy(ctx context.Context, stream, group string) *IntCm return cmd } +func (c cmdable) XGroupCreateConsumer(ctx context.Context, stream, group, consumer string) *IntCmd { + cmd := NewIntCmd(ctx, "xgroup", "createconsumer", stream, group, consumer) + _ = c(ctx, cmd) + return cmd +} + func (c cmdable) XGroupDelConsumer(ctx context.Context, stream, group, consumer string) *IntCmd { cmd := NewIntCmd(ctx, "xgroup", "delconsumer", stream, group, consumer) _ = c(ctx, cmd) @@ -1914,16 +1955,63 @@ func xClaimArgs(a *XClaimArgs) []interface{} { return args } -func (c cmdable) XTrim(ctx context.Context, key string, maxLen int64) *IntCmd { - cmd := NewIntCmd(ctx, "xtrim", key, "maxlen", maxLen) +// xTrim If approx is true, add the "~" parameter, otherwise it is the default "=" (redis default). +// example: +// XTRIM key MAXLEN/MINID threshold LIMIT limit. +// XTRIM key MAXLEN/MINID ~ threshold LIMIT limit. +// The redis-server version is lower than 6.2, please set limit to 0. +func (c cmdable) xTrim( + ctx context.Context, key, strategy string, + approx bool, threshold interface{}, limit int64, +) *IntCmd { + args := make([]interface{}, 0, 7) + args = append(args, "xtrim", key, strategy) + if approx { + args = append(args, "~") + } + args = append(args, threshold) + if limit > 0 { + args = append(args, "limit", limit) + } + cmd := NewIntCmd(ctx, args...) _ = c(ctx, cmd) return cmd } +// Deprecated: use XTrimMaxLen, remove in v9. +func (c cmdable) XTrim(ctx context.Context, key string, maxLen int64) *IntCmd { + return c.xTrim(ctx, key, "maxlen", false, maxLen, 0) +} + +// Deprecated: use XTrimMaxLenApprox, remove in v9. func (c cmdable) XTrimApprox(ctx context.Context, key string, maxLen int64) *IntCmd { - cmd := NewIntCmd(ctx, "xtrim", key, "maxlen", "~", maxLen) - _ = c(ctx, cmd) - return cmd + return c.xTrim(ctx, key, "maxlen", true, maxLen, 0) +} + +// XTrimMaxLen No `~` rules are used, `limit` cannot be used. +// cmd: XTRIM key MAXLEN maxLen +func (c cmdable) XTrimMaxLen(ctx context.Context, key string, maxLen int64) *IntCmd { + return c.xTrim(ctx, key, "maxlen", false, maxLen, 0) +} + +// XTrimMaxLenApprox LIMIT has a bug, please confirm it and use it. +// issue: https://github.com/redis/redis/issues/9046 +// cmd: XTRIM key MAXLEN ~ maxLen LIMIT limit +func (c cmdable) XTrimMaxLenApprox(ctx context.Context, key string, maxLen, limit int64) *IntCmd { + return c.xTrim(ctx, key, "maxlen", true, maxLen, limit) +} + +// XTrimMinID No `~` rules are used, `limit` cannot be used. +// cmd: XTRIM key MINID minID +func (c cmdable) XTrimMinID(ctx context.Context, key string, minID string) *IntCmd { + return c.xTrim(ctx, key, "minid", false, minID, 0) +} + +// XTrimMinIDApprox LIMIT has a bug, please confirm it and use it. +// issue: https://github.com/redis/redis/issues/9046 +// cmd: XTRIM key MINID ~ minID LIMIT limit +func (c cmdable) XTrimMinIDApprox(ctx context.Context, key string, minID string, limit int64) *IntCmd { + return c.xTrim(ctx, key, "minid", true, minID, limit) } func (c cmdable) XInfoConsumers(ctx context.Context, key string, group string) *XInfoConsumersCmd { diff --git a/commands_test.go b/commands_test.go index 11b8592..2bfa3df 100644 --- a/commands_test.go +++ b/commands_test.go @@ -4104,18 +4104,47 @@ var _ = Describe("Commands", func() { Expect(id).To(Equal("3-0")) }) + // TODO remove in v9. It("should XTrim", func() { n, err := client.XTrim(ctx, "stream", 0).Result() Expect(err).NotTo(HaveOccurred()) Expect(n).To(Equal(int64(3))) }) + // TODO remove in v9. It("should XTrimApprox", func() { n, err := client.XTrimApprox(ctx, "stream", 0).Result() Expect(err).NotTo(HaveOccurred()) Expect(n).To(Equal(int64(3))) }) + // TODO XTrimMaxLenApprox/XTrimMinIDApprox There is a bug in the limit parameter. + // TODO Don't test it for now. + // TODO link: https://github.com/redis/redis/issues/9046 + It("should XTrimMaxLen", func() { + n, err := client.XTrimMaxLen(ctx, "stream", 0).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(3))) + }) + + It("should XTrimMaxLenApprox", func() { + n, err := client.XTrimMaxLenApprox(ctx, "stream", 0, 0).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(3))) + }) + + It("should XTrimMinID", func() { + n, err := client.XTrimMinID(ctx, "stream", "4-0").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(3))) + }) + + It("should XTrimMinIDApprox", func() { + n, err := client.XTrimMinIDApprox(ctx, "stream", "4-0", 0).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(3))) + }) + It("should XAdd", func() { id, err := client.XAdd(ctx, &redis.XAddArgs{ Stream: "stream", @@ -4133,6 +4162,9 @@ var _ = Describe("Commands", func() { })) }) + // TODO XAdd There is a bug in the limit parameter. + // TODO Don't test it for now. + // TODO link: https://github.com/redis/redis/issues/9046 It("should XAdd with MaxLen", func() { id, err := client.XAdd(ctx, &redis.XAddArgs{ Stream: "stream", @@ -4148,6 +4180,21 @@ var _ = Describe("Commands", func() { })) }) + It("should XAdd with MinID", func() { + id, err := client.XAdd(ctx, &redis.XAddArgs{ + Stream: "stream", + MinID: "5-0", + ID: "4-0", + Values: map[string]interface{}{"quatro": "quatre"}, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(id).To(Equal("4-0")) + + vals, err := client.XRange(ctx, "stream", "-", "+").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(HaveLen(0)) + }) + It("should XDel", func() { n, err := client.XDel(ctx, "stream", "1-0", "2-0", "3-0").Result() Expect(err).NotTo(HaveOccurred()) @@ -4380,8 +4427,14 @@ var _ = Describe("Commands", func() { infoExt, err = client.XPendingExt(ctx, args).Result() Expect(err).NotTo(HaveOccurred()) Expect(infoExt).To(HaveLen(0)) + }) - n, err := client.XGroupDelConsumer(ctx, "stream", "group", "consumer").Result() + It("should XGroup Create Delete Consumer", func() { + n, err := client.XGroupCreateConsumer(ctx, "stream", "group", "c1").Result() + Expect(err).NotTo(HaveOccurred()) + Expect(n).To(Equal(int64(1))) + + n, err = client.XGroupDelConsumer(ctx, "stream", "group", "consumer").Result() Expect(err).NotTo(HaveOccurred()) Expect(n).To(Equal(int64(3))) }) From 526725c5f8051f74038b223dd6cf1d86f16f04aa Mon Sep 17 00:00:00 2001 From: Vladimir Mihailenco Date: Mon, 21 Jun 2021 09:44:42 +0300 Subject: [PATCH 05/21] Add Bun to readme --- README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e58d867..5f52a55 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,9 @@ - [Examples](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#pkg-examples) - [RealWorld example app](https://github.com/uptrace/go-treemux-realworld-example-app) +> :heart: Please check [Bun](https://bun.uptrace.dev) - fast and simple SQL client for PostgreSQL, +> MySQL, and SQLite. + ## Ecosystem - [Redis Mock](https://github.com/go-redis/redismock). @@ -160,8 +163,3 @@ Lastly, run: ``` go test ``` - -## See also - -- [Fast and flexible ORM](https://github.com/uptrace/bun) -- [msgpack for Go](https://github.com/vmihailenco/msgpack) From f0b2f90143e41ecd84e8e2e4764d763179f8e3be Mon Sep 17 00:00:00 2001 From: monkey92t Date: Wed, 23 Jun 2021 18:47:10 +0800 Subject: [PATCH 06/21] Upgrade the series of commands (#1792) * Upgrade the series of commands Signed-off-by: monkey92t * Cancel the Deprecated mark of ZAddNX and ZAddXX Signed-off-by: monkey92t --- commands.go | 472 ++++++++++++++++++++++++++++++++--------------- commands_test.go | 172 +++++++++++++++++ 2 files changed, 495 insertions(+), 149 deletions(-) diff --git a/commands.go b/commands.go index 32f954e..e12fbc5 100644 --- a/commands.go +++ b/commands.go @@ -248,12 +248,25 @@ type Cmdable interface { BZPopMax(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd BZPopMin(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd + + // TODO: remove + // ZAddCh + // ZIncr + // ZAddNXCh + // ZAddXXCh + // ZIncrNX + // ZIncrXX + // in v9. + // use ZAddArgs and ZAddArgsIncr. + ZAdd(ctx context.Context, key string, members ...*Z) *IntCmd ZAddNX(ctx context.Context, key string, members ...*Z) *IntCmd ZAddXX(ctx context.Context, key string, members ...*Z) *IntCmd ZAddCh(ctx context.Context, key string, members ...*Z) *IntCmd ZAddNXCh(ctx context.Context, key string, members ...*Z) *IntCmd ZAddXXCh(ctx context.Context, key string, members ...*Z) *IntCmd + ZAddArgs(ctx context.Context, key string, args ZAddArgs) *IntCmd + ZAddArgsIncr(ctx context.Context, key string, args ZAddArgs) *FloatCmd ZIncr(ctx context.Context, key string, member *Z) *FloatCmd ZIncrNX(ctx context.Context, key string, member *Z) *FloatCmd ZIncrXX(ctx context.Context, key string, member *Z) *FloatCmd @@ -272,6 +285,9 @@ type Cmdable interface { ZRangeByScore(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd ZRangeByLex(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd ZRangeByScoreWithScores(ctx context.Context, key string, opt *ZRangeBy) *ZSliceCmd + ZRangeArgs(ctx context.Context, z ZRangeArgs) *StringSliceCmd + ZRangeArgsWithScores(ctx context.Context, z ZRangeArgs) *ZSliceCmd + ZRangeStore(ctx context.Context, dst string, z ZRangeArgs) *IntCmd ZRank(ctx context.Context, key, member string) *IntCmd ZRem(ctx context.Context, key string, members ...interface{}) *IntCmd ZRemRangeByRank(ctx context.Context, key string, start, stop int64) *IntCmd @@ -285,6 +301,8 @@ type Cmdable interface { ZRevRank(ctx context.Context, key, member string) *IntCmd ZScore(ctx context.Context, key, member string) *FloatCmd ZUnionStore(ctx context.Context, dest string, store *ZStore) *IntCmd + ZUnion(ctx context.Context, store ZStore) *StringSliceCmd + ZUnionWithScores(ctx context.Context, store ZStore) *ZSliceCmd ZRandMember(ctx context.Context, key string, count int, withScores bool) *StringSliceCmd ZDiff(ctx context.Context, keys ...string) *StringSliceCmd ZDiffWithScores(ctx context.Context, keys ...string) *ZSliceCmd @@ -393,7 +411,7 @@ func (c statefulCmdable) Auth(ctx context.Context, password string) *StatusCmd { return cmd } -// Perform an AUTH command, using the given user and pass. +// AuthACL Perform an AUTH command, using the given user and pass. // Should be used to authenticate the current connection with one of the connections defined in the ACL list // when connecting to a Redis 6.0 instance, or greater, that is using the Redis ACL system. func (c statefulCmdable) AuthACL(ctx context.Context, username, password string) *StatusCmd { @@ -454,7 +472,7 @@ func (c cmdable) Ping(ctx context.Context) *StatusCmd { return cmd } -func (c cmdable) Quit(ctx context.Context) *StatusCmd { +func (c cmdable) Quit(_ context.Context) *StatusCmd { panic("not implemented") } @@ -717,7 +735,7 @@ func (c cmdable) DecrBy(ctx context.Context, key string, decrement int64) *IntCm return cmd } -// Redis `GET key` command. It returns redis.Nil error when key does not exist. +// Get Redis `GET key` command. It returns redis.Nil error when key does not exist. func (c cmdable) Get(ctx context.Context, key string) *StringCmd { cmd := NewStringCmd(ctx, "get", key) _ = c(ctx, cmd) @@ -736,7 +754,7 @@ func (c cmdable) GetSet(ctx context.Context, key string, value interface{}) *Str return cmd } -// An expiration of zero removes the TTL associated with the key (i.e. GETEX key persist). +// GetEx An expiration of zero removes the TTL associated with the key (i.e. GETEX key persist). // Requires Redis >= 6.2.0. func (c cmdable) GetEx(ctx context.Context, key string, expiration time.Duration) *StringCmd { args := make([]interface{}, 0, 4) @@ -756,7 +774,7 @@ func (c cmdable) GetEx(ctx context.Context, key string, expiration time.Duration return cmd } -// redis-server version >= 6.2.0. +// GetDel redis-server version >= 6.2.0. func (c cmdable) GetDel(ctx context.Context, key string) *StringCmd { cmd := NewStringCmd(ctx, "getdel", key) _ = c(ctx, cmd) @@ -818,7 +836,7 @@ func (c cmdable) MSetNX(ctx context.Context, values ...interface{}) *BoolCmd { return cmd } -// Redis `SET key value [expiration]` command. +// Set Redis `SET key value [expiration]` command. // Use expiration for `SETEX`-like behavior. // // Zero expiration means the key has no expiration time. @@ -893,14 +911,14 @@ func (c cmdable) SetArgs(ctx context.Context, key string, value interface{}, a S return cmd } -// Redis `SETEX key expiration value` command. +// SetEX 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) _ = c(ctx, cmd) return cmd } -// Redis `SET key value [expiration] NX` command. +// SetNX Redis `SET key value [expiration] NX` command. // // Zero expiration means the key has no expiration time. // KeepTTL(-1) expiration is a Redis KEEPTTL option to keep existing TTL. @@ -924,7 +942,7 @@ func (c cmdable) SetNX(ctx context.Context, key string, value interface{}, expir return cmd } -// Redis `SET key value [expiration] XX` command. +// SetXX Redis `SET key value [expiration] XX` command. // // Zero expiration means the key has no expiration time. // KeepTTL(-1) expiration is a Redis KEEPTTL option to keep existing TTL. @@ -1235,7 +1253,7 @@ func (c cmdable) HVals(ctx context.Context, key string) *StringSliceCmd { return cmd } -// redis-server version >= 6.2.0. +// HRandField redis-server version >= 6.2.0. func (c cmdable) HRandField(ctx context.Context, key string, count int, withValues bool) *StringSliceCmd { args := make([]interface{}, 0, 4) @@ -1528,7 +1546,7 @@ func (c cmdable) SIsMember(ctx context.Context, key string, member interface{}) return cmd } -// Redis `SMISMEMBER key member [member ...]` command. +// SMIsMember Redis `SMISMEMBER key member [member ...]` command. func (c cmdable) SMIsMember(ctx context.Context, key string, members ...interface{}) *BoolSliceCmd { args := make([]interface{}, 2, 2+len(members)) args[0] = "smismember" @@ -1539,14 +1557,14 @@ func (c cmdable) SMIsMember(ctx context.Context, key string, members ...interfac return cmd } -// Redis `SMEMBERS key` command output as a slice. +// SMembers Redis `SMEMBERS key` command output as a slice. func (c cmdable) SMembers(ctx context.Context, key string) *StringSliceCmd { cmd := NewStringSliceCmd(ctx, "smembers", key) _ = c(ctx, cmd) return cmd } -// Redis `SMEMBERS key` command output as a map. +// SMembersMap Redis `SMEMBERS key` command output as a map. func (c cmdable) SMembersMap(ctx context.Context, key string) *StringStructMapCmd { cmd := NewStringStructMapCmd(ctx, "smembers", key) _ = c(ctx, cmd) @@ -1559,28 +1577,28 @@ func (c cmdable) SMove(ctx context.Context, source, destination string, member i return cmd } -// Redis `SPOP key` command. +// SPop Redis `SPOP key` command. func (c cmdable) SPop(ctx context.Context, key string) *StringCmd { cmd := NewStringCmd(ctx, "spop", key) _ = c(ctx, cmd) return cmd } -// Redis `SPOP key count` command. +// SPopN Redis `SPOP key count` command. func (c cmdable) SPopN(ctx context.Context, key string, count int64) *StringSliceCmd { cmd := NewStringSliceCmd(ctx, "spop", key, count) _ = c(ctx, cmd) return cmd } -// Redis `SRANDMEMBER key` command. +// SRandMember Redis `SRANDMEMBER key` command. func (c cmdable) SRandMember(ctx context.Context, key string) *StringCmd { cmd := NewStringCmd(ctx, "srandmember", key) _ = c(ctx, cmd) return cmd } -// Redis `SRANDMEMBER key count` command. +// SRandMemberN Redis `SRANDMEMBER key count` command. func (c cmdable) SRandMemberN(ctx context.Context, key string, count int64) *StringSliceCmd { cmd := NewStringSliceCmd(ctx, "srandmember", key, count) _ = c(ctx, cmd) @@ -2059,7 +2077,7 @@ type ZWithKey struct { Key string } -// ZStore is used as an arg to ZInterStore and ZUnionStore. +// ZStore is used as an arg to ZInter/ZInterStore and ZUnion/ZUnionStore. type ZStore struct { Keys []string Weights []float64 @@ -2067,7 +2085,7 @@ type ZStore struct { Aggregate string } -func (z *ZStore) len() (n int) { +func (z ZStore) len() (n int) { n = len(z.Keys) if len(z.Weights) > 0 { n += 1 + len(z.Weights) @@ -2078,7 +2096,23 @@ func (z *ZStore) len() (n int) { return n } -// Redis `BZPOPMAX key [key ...] timeout` command. +func (z ZStore) appendArgs(args []interface{}) []interface{} { + for _, key := range z.Keys { + args = append(args, key) + } + if len(z.Weights) > 0 { + args = append(args, "weights") + for _, weights := range z.Weights { + args = append(args, weights) + } + } + if z.Aggregate != "" { + args = append(args, "aggregate", z.Aggregate) + } + return args +} + +// BZPopMax Redis `BZPOPMAX key [key ...] timeout` command. func (c cmdable) BZPopMax(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd { args := make([]interface{}, 1+len(keys)+1) args[0] = "bzpopmax" @@ -2092,7 +2126,7 @@ func (c cmdable) BZPopMax(ctx context.Context, timeout time.Duration, keys ...st return cmd } -// Redis `BZPOPMIN key [key ...] timeout` command. +// BZPopMin Redis `BZPOPMIN key [key ...] timeout` command. func (c cmdable) BZPopMin(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd { args := make([]interface{}, 1+len(keys)+1) args[0] = "bzpopmin" @@ -2106,96 +2140,169 @@ func (c cmdable) BZPopMin(ctx context.Context, timeout time.Duration, keys ...st return cmd } -func (c cmdable) zAdd(ctx context.Context, a []interface{}, n int, members ...*Z) *IntCmd { - for i, m := range members { - a[n+2*i] = m.Score - a[n+2*i+1] = m.Member +// ZAddArgs WARN: The GT, LT and NX options are mutually exclusive. +type ZAddArgs struct { + NX bool + XX bool + LT bool + GT bool + Ch bool + Members []Z +} + +func (c cmdable) zAddArgs(key string, args ZAddArgs, incr bool) []interface{} { + a := make([]interface{}, 0, 6+2*len(args.Members)) + a = append(a, "zadd", key) + + // The GT, LT and NX options are mutually exclusive. + if args.NX { + a = append(a, "nx") + } else { + if args.XX { + a = append(a, "xx") + } + if args.GT { + a = append(a, "gt") + } else if args.LT { + a = append(a, "lt") + } } - cmd := NewIntCmd(ctx, a...) + if args.Ch { + a = append(a, "ch") + } + if incr { + a = append(a, "incr") + } + for _, m := range args.Members { + a = append(a, m.Score) + a = append(a, m.Member) + } + return a +} + +func (c cmdable) ZAddArgs(ctx context.Context, key string, args ZAddArgs) *IntCmd { + cmd := NewIntCmd(ctx, c.zAddArgs(key, args, false)...) _ = c(ctx, cmd) return cmd } -// Redis `ZADD key score member [score member ...]` command. +func (c cmdable) ZAddArgsIncr(ctx context.Context, key string, args ZAddArgs) *FloatCmd { + cmd := NewFloatCmd(ctx, c.zAddArgs(key, args, true)...) + _ = c(ctx, cmd) + return cmd +} + +// TODO: Compatible with v8 api, will be removed in v9. +func (c cmdable) zAdd(ctx context.Context, key string, args ZAddArgs, members ...*Z) *IntCmd { + args.Members = make([]Z, len(members)) + for i, m := range members { + args.Members[i] = *m + } + cmd := NewIntCmd(ctx, c.zAddArgs(key, args, false)...) + _ = c(ctx, cmd) + return cmd +} + +// ZAdd Redis `ZADD key score member [score member ...]` command. func (c cmdable) ZAdd(ctx context.Context, key string, members ...*Z) *IntCmd { - const n = 2 - a := make([]interface{}, n+2*len(members)) - a[0], a[1] = "zadd", key - return c.zAdd(ctx, a, n, members...) + return c.zAdd(ctx, key, ZAddArgs{}, members...) } -// Redis `ZADD key NX score member [score member ...]` command. +// ZAddNX Redis `ZADD key NX score member [score member ...]` command. func (c cmdable) ZAddNX(ctx context.Context, key string, members ...*Z) *IntCmd { - const n = 3 - a := make([]interface{}, n+2*len(members)) - a[0], a[1], a[2] = "zadd", key, "nx" - return c.zAdd(ctx, a, n, members...) + return c.zAdd(ctx, key, ZAddArgs{ + NX: true, + }, members...) } -// Redis `ZADD key XX score member [score member ...]` command. +// ZAddXX Redis `ZADD key XX score member [score member ...]` command. func (c cmdable) ZAddXX(ctx context.Context, key string, members ...*Z) *IntCmd { - const n = 3 - a := make([]interface{}, n+2*len(members)) - a[0], a[1], a[2] = "zadd", key, "xx" - return c.zAdd(ctx, a, n, members...) + return c.zAdd(ctx, key, ZAddArgs{ + XX: true, + }, members...) } -// Redis `ZADD key CH score member [score member ...]` command. +// ZAddCh Redis `ZADD key CH score member [score member ...]` command. +// Deprecated: Use +// client.ZAddArgs(ctx, ZAddArgs{ +// Ch: true, +// Members: []Z, +// }) +// remove in v9. func (c cmdable) ZAddCh(ctx context.Context, key string, members ...*Z) *IntCmd { - const n = 3 - a := make([]interface{}, n+2*len(members)) - a[0], a[1], a[2] = "zadd", key, "ch" - return c.zAdd(ctx, a, n, members...) + return c.zAdd(ctx, key, ZAddArgs{ + Ch: true, + }, members...) } -// Redis `ZADD key NX CH score member [score member ...]` command. +// ZAddNXCh Redis `ZADD key NX CH score member [score member ...]` command. +// Deprecated: Use +// client.ZAddArgs(ctx, ZAddArgs{ +// NX: true, +// Ch: true, +// Members: []Z, +// }) +// remove in v9. func (c cmdable) ZAddNXCh(ctx context.Context, key string, members ...*Z) *IntCmd { - const n = 4 - a := make([]interface{}, n+2*len(members)) - a[0], a[1], a[2], a[3] = "zadd", key, "nx", "ch" - return c.zAdd(ctx, a, n, members...) + return c.zAdd(ctx, key, ZAddArgs{ + NX: true, + Ch: true, + }, members...) } -// Redis `ZADD key XX CH score member [score member ...]` command. +// ZAddXXCh Redis `ZADD key XX CH score member [score member ...]` command. +// Deprecated: Use +// client.ZAddArgs(ctx, ZAddArgs{ +// XX: true, +// Ch: true, +// Members: []Z, +// }) +// remove in v9. func (c cmdable) ZAddXXCh(ctx context.Context, key string, members ...*Z) *IntCmd { - const n = 4 - a := make([]interface{}, n+2*len(members)) - a[0], a[1], a[2], a[3] = "zadd", key, "xx", "ch" - return c.zAdd(ctx, a, n, members...) + return c.zAdd(ctx, key, ZAddArgs{ + XX: true, + Ch: true, + }, members...) } -func (c cmdable) zIncr(ctx context.Context, a []interface{}, n int, members ...*Z) *FloatCmd { - for i, m := range members { - a[n+2*i] = m.Score - a[n+2*i+1] = m.Member - } - cmd := NewFloatCmd(ctx, a...) - _ = c(ctx, cmd) - return cmd -} - -// Redis `ZADD key INCR score member` command. +// ZIncr Redis `ZADD key INCR score member` command. +// Deprecated: Use +// client.ZAddArgsIncr(ctx, ZAddArgs{ +// Members: []Z, +// }) +// remove in v9. func (c cmdable) ZIncr(ctx context.Context, key string, member *Z) *FloatCmd { - const n = 3 - a := make([]interface{}, n+2) - a[0], a[1], a[2] = "zadd", key, "incr" - return c.zIncr(ctx, a, n, member) + return c.ZAddArgsIncr(ctx, key, ZAddArgs{ + Members: []Z{*member}, + }) } -// Redis `ZADD key NX INCR score member` command. +// ZIncrNX Redis `ZADD key NX INCR score member` command. +// Deprecated: Use +// client.ZAddArgsIncr(ctx, ZAddArgs{ +// NX: true, +// Members: []Z, +// }) +// remove in v9. func (c cmdable) ZIncrNX(ctx context.Context, key string, member *Z) *FloatCmd { - const n = 4 - a := make([]interface{}, n+2) - a[0], a[1], a[2], a[3] = "zadd", key, "incr", "nx" - return c.zIncr(ctx, a, n, member) + return c.ZAddArgsIncr(ctx, key, ZAddArgs{ + NX: true, + Members: []Z{*member}, + }) } -// Redis `ZADD key XX INCR score member` command. +// ZIncrXX Redis `ZADD key XX INCR score member` command. +// Deprecated: Use +// client.ZAddArgsIncr(ctx, ZAddArgs{ +// XX: true, +// Members: []Z, +// }) +// remove in v9. func (c cmdable) ZIncrXX(ctx context.Context, key string, member *Z) *FloatCmd { - const n = 4 - a := make([]interface{}, n+2) - a[0], a[1], a[2], a[3] = "zadd", key, "incr", "xx" - return c.zIncr(ctx, a, n, member) + return c.ZAddArgsIncr(ctx, key, ZAddArgs{ + XX: true, + Members: []Z{*member}, + }) } func (c cmdable) ZCard(ctx context.Context, key string) *IntCmd { @@ -2225,18 +2332,7 @@ func (c cmdable) ZIncrBy(ctx context.Context, key string, increment float64, mem func (c cmdable) ZInterStore(ctx context.Context, destination string, store *ZStore) *IntCmd { args := make([]interface{}, 0, 3+store.len()) args = append(args, "zinterstore", destination, len(store.Keys)) - for _, key := range store.Keys { - args = append(args, key) - } - if len(store.Weights) > 0 { - args = append(args, "weights") - for _, weight := range store.Weights { - args = append(args, weight) - } - } - if store.Aggregate != "" { - args = append(args, "aggregate", store.Aggregate) - } + args = store.appendArgs(args) cmd := NewIntCmd(ctx, args...) cmd.setFirstKeyPos(3) _ = c(ctx, cmd) @@ -2246,19 +2342,7 @@ func (c cmdable) ZInterStore(ctx context.Context, destination string, store *ZSt func (c cmdable) ZInter(ctx context.Context, store *ZStore) *StringSliceCmd { args := make([]interface{}, 0, 2+store.len()) args = append(args, "zinter", len(store.Keys)) - for _, key := range store.Keys { - args = append(args, key) - } - if len(store.Weights) > 0 { - args = append(args, "weights") - for _, weights := range store.Weights { - args = append(args, weights) - } - } - - if store.Aggregate != "" { - args = append(args, "aggregate", store.Aggregate) - } + args = store.appendArgs(args) cmd := NewStringSliceCmd(ctx, args...) cmd.setFirstKeyPos(2) _ = c(ctx, cmd) @@ -2268,18 +2352,7 @@ func (c cmdable) ZInter(ctx context.Context, store *ZStore) *StringSliceCmd { func (c cmdable) ZInterWithScores(ctx context.Context, store *ZStore) *ZSliceCmd { args := make([]interface{}, 0, 3+store.len()) args = append(args, "zinter", len(store.Keys)) - for _, key := range store.Keys { - args = append(args, key) - } - if len(store.Weights) > 0 { - args = append(args, "weights") - for _, weights := range store.Weights { - args = append(args, weights) - } - } - if store.Aggregate != "" { - args = append(args, "aggregate", store.Aggregate) - } + args = store.appendArgs(args) args = append(args, "withscores") cmd := NewZSliceCmd(ctx, args...) cmd.setFirstKeyPos(2) @@ -2339,29 +2412,112 @@ func (c cmdable) ZPopMin(ctx context.Context, key string, count ...int64) *ZSlic return cmd } -func (c cmdable) zRange(ctx context.Context, key string, start, stop int64, withScores bool) *StringSliceCmd { - args := []interface{}{ - "zrange", - key, - start, - stop, +// ZRangeArgs is all the options of the ZRange command. +// In version> 6.2.0, you can replace the(cmd): +// ZREVRANGE, +// ZRANGEBYSCORE, +// ZREVRANGEBYSCORE, +// ZRANGEBYLEX, +// ZREVRANGEBYLEX. +// Please pay attention to your redis-server version. +// +// Rev, ByScore, ByLex and Offset+Count options require redis-server 6.2.0 and higher. +type ZRangeArgs struct { + Key string + + // When the ByScore option is provided, the open interval(exclusive) can be set. + // By default, the score intervals specified by and are closed (inclusive). + // It is similar to the deprecated(6.2.0+) ZRangeByScore command. + // For example: + // ZRangeArgs{ + // Key: "example-key", + // Start: "(3", + // Stop: 8, + // ByScore: true, + // } + // cmd: "ZRange example-key (3 8 ByScore" (3 < score <= 8). + // + // For the ByLex option, it is similar to the deprecated(6.2.0+) ZRangeByLex command. + // You can set the and options as follows: + // ZRangeArgs{ + // Key: "example-key", + // Start: "[abc", + // Stop: "(def", + // ByLex: true, + // } + // cmd: "ZRange example-key [abc (def ByLex" + // + // For normal cases (ByScore==false && ByLex==false), and should be set to the index range (int). + // You can read the documentation for more information: https://redis.io/commands/zrange + Start interface{} + Stop interface{} + + // The ByScore and ByLex options are mutually exclusive. + ByScore bool + ByLex bool + + Rev bool + + // limit offset count. + Offset int64 + Count int64 +} + +func (z ZRangeArgs) appendArgs(args []interface{}) []interface{} { + // For Rev+ByScore/ByLex, we need to adjust the position of and . + if z.Rev && (z.ByScore || z.ByLex) { + args = append(args, z.Key, z.Stop, z.Start) + } else { + args = append(args, z.Key, z.Start, z.Stop) } - if withScores { - args = append(args, "withscores") + + if z.ByScore { + args = append(args, "byscore") + } else if z.ByLex { + args = append(args, "bylex") } + if z.Rev { + args = append(args, "rev") + } + if z.Offset != 0 || z.Count != 0 { + args = append(args, "limit", z.Offset, z.Count) + } + return args +} + +func (c cmdable) ZRangeArgs(ctx context.Context, z ZRangeArgs) *StringSliceCmd { + args := make([]interface{}, 0, 9) + args = append(args, "zrange") + args = z.appendArgs(args) cmd := NewStringSliceCmd(ctx, args...) _ = c(ctx, cmd) return cmd } +func (c cmdable) ZRangeArgsWithScores(ctx context.Context, z ZRangeArgs) *ZSliceCmd { + args := make([]interface{}, 0, 10) + args = append(args, "zrange") + args = z.appendArgs(args) + args = append(args, "withscores") + cmd := NewZSliceCmd(ctx, args...) + _ = c(ctx, cmd) + return cmd +} + func (c cmdable) ZRange(ctx context.Context, key string, start, stop int64) *StringSliceCmd { - return c.zRange(ctx, key, start, stop, false) + return c.ZRangeArgs(ctx, ZRangeArgs{ + Key: key, + Start: start, + Stop: stop, + }) } func (c cmdable) ZRangeWithScores(ctx context.Context, key string, start, stop int64) *ZSliceCmd { - cmd := NewZSliceCmd(ctx, "zrange", key, start, stop, "withscores") - _ = c(ctx, cmd) - return cmd + return c.ZRangeArgsWithScores(ctx, ZRangeArgs{ + Key: key, + Start: start, + Stop: stop, + }) } type ZRangeBy struct { @@ -2410,6 +2566,15 @@ func (c cmdable) ZRangeByScoreWithScores(ctx context.Context, key string, opt *Z return cmd } +func (c cmdable) ZRangeStore(ctx context.Context, dst string, z ZRangeArgs) *IntCmd { + args := make([]interface{}, 0, 10) + args = append(args, "zrangestore", dst) + args = z.appendArgs(args) + cmd := NewIntCmd(ctx, args...) + _ = c(ctx, cmd) + return cmd +} + func (c cmdable) ZRank(ctx context.Context, key, member string) *IntCmd { cmd := NewIntCmd(ctx, "zrank", key, member) _ = c(ctx, cmd) @@ -2512,29 +2677,38 @@ func (c cmdable) ZScore(ctx context.Context, key, member string) *FloatCmd { return cmd } +func (c cmdable) ZUnion(ctx context.Context, store ZStore) *StringSliceCmd { + args := make([]interface{}, 0, 2+store.len()) + args = append(args, "zunion", len(store.Keys)) + args = store.appendArgs(args) + cmd := NewStringSliceCmd(ctx, args...) + cmd.setFirstKeyPos(2) + _ = c(ctx, cmd) + return cmd +} + +func (c cmdable) ZUnionWithScores(ctx context.Context, store ZStore) *ZSliceCmd { + args := make([]interface{}, 0, 3+store.len()) + args = append(args, "zunion", len(store.Keys)) + args = store.appendArgs(args) + args = append(args, "withscores") + cmd := NewZSliceCmd(ctx, args...) + cmd.setFirstKeyPos(2) + _ = c(ctx, cmd) + return cmd +} + func (c cmdable) ZUnionStore(ctx context.Context, dest string, store *ZStore) *IntCmd { args := make([]interface{}, 0, 3+store.len()) args = append(args, "zunionstore", dest, len(store.Keys)) - for _, key := range store.Keys { - args = append(args, key) - } - if len(store.Weights) > 0 { - args = append(args, "weights") - for _, weight := range store.Weights { - args = append(args, weight) - } - } - if store.Aggregate != "" { - args = append(args, "aggregate", store.Aggregate) - } - + args = store.appendArgs(args) cmd := NewIntCmd(ctx, args...) cmd.setFirstKeyPos(3) _ = c(ctx, cmd) return cmd } -// redis-server version >= 6.2.0. +// ZRandMember redis-server version >= 6.2.0. func (c cmdable) ZRandMember(ctx context.Context, key string, count int, withScores bool) *StringSliceCmd { args := make([]interface{}, 0, 4) @@ -2549,7 +2723,7 @@ func (c cmdable) ZRandMember(ctx context.Context, key string, count int, withSco return cmd } -// redis-server version >= 6.2.0. +// ZDiff redis-server version >= 6.2.0. func (c cmdable) ZDiff(ctx context.Context, keys ...string) *StringSliceCmd { args := make([]interface{}, 2+len(keys)) args[0] = "zdiff" @@ -2564,7 +2738,7 @@ func (c cmdable) ZDiff(ctx context.Context, keys ...string) *StringSliceCmd { return cmd } -// redis-server version >= 6.2.0. +// ZDiffWithScores redis-server version >= 6.2.0. func (c cmdable) ZDiffWithScores(ctx context.Context, keys ...string) *ZSliceCmd { args := make([]interface{}, 3+len(keys)) args[0] = "zdiff" @@ -2580,7 +2754,7 @@ func (c cmdable) ZDiffWithScores(ctx context.Context, keys ...string) *ZSliceCmd return cmd } -// redis-server version >=6.2.0. +// ZDiffStore redis-server version >=6.2.0. func (c cmdable) ZDiffStore(ctx context.Context, destination string, keys ...string) *IntCmd { args := make([]interface{}, 0, 3+len(keys)) args = append(args, "zdiffstore", destination, len(keys)) @@ -2814,7 +2988,7 @@ func (c cmdable) SlowLogGet(ctx context.Context, num int64) *SlowLogCmd { return cmd } -func (c cmdable) Sync(ctx context.Context) { +func (c cmdable) Sync(_ context.Context) { panic("not implemented") } @@ -3132,7 +3306,7 @@ func (c cmdable) GeoRadiusStore( return cmd } -// GeoRadius is a read-only GEORADIUSBYMEMBER_RO command. +// GeoRadiusByMember is a read-only GEORADIUSBYMEMBER_RO command. func (c cmdable) GeoRadiusByMember( ctx context.Context, key, member string, query *GeoRadiusQuery, ) *GeoLocationCmd { diff --git a/commands_test.go b/commands_test.go index 2bfa3df..1557312 100644 --- a/commands_test.go +++ b/commands_test.go @@ -2940,6 +2940,42 @@ var _ = Describe("Commands", func() { }})) }) + It("should ZAddArgs", func() { + // Test only the GT+LT options. + added, err := client.ZAddArgs(ctx, "zset", redis.ZAddArgs{ + GT: true, + Members: []redis.Z{{Score: 1, Member: "one"}}, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(1))) + + vals, err := client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 1, Member: "one"}})) + + added, err = client.ZAddArgs(ctx, "zset", redis.ZAddArgs{ + GT: true, + Members: []redis.Z{{Score: 2, Member: "one"}}, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(0))) + + vals, err = client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}})) + + added, err = client.ZAddArgs(ctx, "zset", redis.ZAddArgs{ + LT: true, + Members: []redis.Z{{Score: 1, Member: "one"}}, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(0))) + + vals, err = client.ZRangeWithScores(ctx, "zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(vals).To(Equal([]redis.Z{{Score: 1, Member: "one"}})) + }) + It("should ZAddNX", func() { added, err := client.ZAddNX(ctx, "zset", &redis.Z{ Score: 1, @@ -2995,6 +3031,7 @@ var _ = Describe("Commands", func() { Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}})) }) + // TODO: remove in v9. It("should ZAddCh", func() { changed, err := client.ZAddCh(ctx, "zset", &redis.Z{ Score: 1, @@ -3011,6 +3048,7 @@ var _ = Describe("Commands", func() { Expect(changed).To(Equal(int64(0))) }) + // TODO: remove in v9. It("should ZAddNXCh", func() { changed, err := client.ZAddNXCh(ctx, "zset", &redis.Z{ Score: 1, @@ -3038,6 +3076,7 @@ var _ = Describe("Commands", func() { }})) }) + // TODO: remove in v9. It("should ZAddXXCh", func() { changed, err := client.ZAddXXCh(ctx, "zset", &redis.Z{ Score: 1, @@ -3069,6 +3108,7 @@ var _ = Describe("Commands", func() { Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}})) }) + // TODO: remove in v9. It("should ZIncr", func() { score, err := client.ZIncr(ctx, "zset", &redis.Z{ Score: 1, @@ -3093,6 +3133,7 @@ var _ = Describe("Commands", func() { Expect(vals).To(Equal([]redis.Z{{Score: 2, Member: "one"}})) }) + // TODO: remove in v9. It("should ZIncrNX", func() { score, err := client.ZIncrNX(ctx, "zset", &redis.Z{ Score: 1, @@ -3117,6 +3158,7 @@ var _ = Describe("Commands", func() { Expect(vals).To(Equal([]redis.Z{{Score: 1, Member: "one"}})) }) + // TODO: remove in v9. It("should ZIncrXX", func() { score, err := client.ZIncrXX(ctx, "zset", &redis.Z{ Score: 1, @@ -3475,6 +3517,68 @@ var _ = Describe("Commands", func() { }})) }) + It("should ZRangeArgs", func() { + added, err := client.ZAddArgs(ctx, "zset", redis.ZAddArgs{ + Members: []redis.Z{ + {Score: 1, Member: "one"}, + {Score: 2, Member: "two"}, + {Score: 3, Member: "three"}, + {Score: 4, Member: "four"}, + }, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(4))) + + zRange, err := client.ZRangeArgs(ctx, redis.ZRangeArgs{ + Key: "zset", + Start: 1, + Stop: 4, + ByScore: true, + Rev: true, + Offset: 1, + Count: 2, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(zRange).To(Equal([]string{"three", "two"})) + + zRange, err = client.ZRangeArgs(ctx, redis.ZRangeArgs{ + Key: "zset", + Start: "-", + Stop: "+", + ByLex: true, + Rev: true, + Offset: 2, + Count: 2, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(zRange).To(Equal([]string{"two", "one"})) + + zRange, err = client.ZRangeArgs(ctx, redis.ZRangeArgs{ + Key: "zset", + Start: "(1", + Stop: "(4", + ByScore: true, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(zRange).To(Equal([]string{"two", "three"})) + + // withScores. + zSlice, err := client.ZRangeArgsWithScores(ctx, redis.ZRangeArgs{ + Key: "zset", + Start: 1, + Stop: 4, + ByScore: true, + Rev: true, + Offset: 1, + Count: 2, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(zSlice).To(Equal([]redis.Z{ + {Score: 3, Member: "three"}, + {Score: 2, Member: "two"}, + })) + }) + It("should ZRangeByScore", func() { err := client.ZAdd(ctx, "zset", &redis.Z{Score: 1, Member: "one"}).Err() Expect(err).NotTo(HaveOccurred()) @@ -3610,6 +3714,35 @@ var _ = Describe("Commands", func() { Expect(vals).To(Equal([]redis.Z{})) }) + It("should ZRangeStore", func() { + added, err := client.ZAddArgs(ctx, "zset", redis.ZAddArgs{ + Members: []redis.Z{ + {Score: 1, Member: "one"}, + {Score: 2, Member: "two"}, + {Score: 3, Member: "three"}, + {Score: 4, Member: "four"}, + }, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(added).To(Equal(int64(4))) + + rangeStore, err := client.ZRangeStore(ctx, "new-zset", redis.ZRangeArgs{ + Key: "zset", + Start: 1, + Stop: 4, + ByScore: true, + Rev: true, + Offset: 1, + Count: 2, + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(rangeStore).To(Equal(int64(2))) + + zRange, err := client.ZRange(ctx, "new-zset", 0, -1).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(zRange).To(Equal([]string{"two", "three"})) + }) + It("should ZRank", func() { err := client.ZAdd(ctx, "zset", &redis.Z{Score: 1, Member: "one"}).Err() Expect(err).NotTo(HaveOccurred()) @@ -3907,6 +4040,45 @@ var _ = Describe("Commands", func() { Expect(zScore.Val()).To(Equal(float64(1.001))) }) + It("should ZUnion", func() { + err := client.ZAddArgs(ctx, "zset1", redis.ZAddArgs{ + Members: []redis.Z{ + {Score: 1, Member: "one"}, + {Score: 2, Member: "two"}, + }, + }).Err() + Expect(err).NotTo(HaveOccurred()) + + err = client.ZAddArgs(ctx, "zset2", redis.ZAddArgs{ + Members: []redis.Z{ + {Score: 1, Member: "one"}, + {Score: 2, Member: "two"}, + {Score: 3, Member: "three"}, + }, + }).Err() + Expect(err).NotTo(HaveOccurred()) + + union, err := client.ZUnion(ctx, redis.ZStore{ + Keys: []string{"zset1", "zset2"}, + Weights: []float64{2, 3}, + Aggregate: "sum", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(union).To(Equal([]string{"one", "three", "two"})) + + unionScores, err := client.ZUnionWithScores(ctx, redis.ZStore{ + Keys: []string{"zset1", "zset2"}, + Weights: []float64{2, 3}, + Aggregate: "sum", + }).Result() + Expect(err).NotTo(HaveOccurred()) + Expect(unionScores).To(Equal([]redis.Z{ + {Score: 5, Member: "one"}, + {Score: 9, Member: "three"}, + {Score: 10, Member: "two"}, + })) + }) + It("should ZUnionStore", func() { err := client.ZAdd(ctx, "zset1", &redis.Z{Score: 1, Member: "one"}).Err() Expect(err).NotTo(HaveOccurred()) From 960e4d6cf0b378c8444714e2110263a720fa90ad Mon Sep 17 00:00:00 2001 From: monkey92t Date: Fri, 25 Jun 2021 11:58:21 +0800 Subject: [PATCH 07/21] Explain the use restrictions of KeepTTL. (#1799) Signed-off-by: monkey92t --- commands.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/commands.go b/commands.go index e12fbc5..51a4ef8 100644 --- a/commands.go +++ b/commands.go @@ -10,6 +10,7 @@ import ( ) // KeepTTL is an option for Set command to keep key's existing TTL. +// It requires your redis-server version >= 6.0 (Otherwise you will receive an error: (error) ERR syntax error). // For example: // // rdb.Set(ctx, key, value, redis.KeepTTL) @@ -841,6 +842,7 @@ func (c cmdable) MSetNX(ctx context.Context, values ...interface{}) *BoolCmd { // // Zero expiration means the key has no expiration time. // KeepTTL(-1) expiration is a Redis KEEPTTL option to keep existing TTL. +// It requires your redis-server version >= 6.0 (Otherwise you will receive an error: (error) ERR syntax error). func (c cmdable) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd { args := make([]interface{}, 3, 5) args[0] = "set" @@ -874,6 +876,7 @@ type SetArgs struct { Get bool // KeepTTL is a Redis KEEPTTL option to keep existing TTL. + // It requires your redis-server version >= 6.0 (Otherwise you will receive an error: (error) ERR syntax error). KeepTTL bool } @@ -922,6 +925,7 @@ func (c cmdable) SetEX(ctx context.Context, key string, value interface{}, expir // // Zero expiration means the key has no expiration time. // KeepTTL(-1) expiration is a Redis KEEPTTL option to keep existing TTL. +// It requires your redis-server version >= 6.0 (Otherwise you will receive an error: (error) ERR syntax error). func (c cmdable) SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd { var cmd *BoolCmd switch expiration { @@ -946,6 +950,7 @@ func (c cmdable) SetNX(ctx context.Context, key string, value interface{}, expir // // Zero expiration means the key has no expiration time. // KeepTTL(-1) expiration is a Redis KEEPTTL option to keep existing TTL. +// It requires your redis-server version >= 6.0 (Otherwise you will receive an error: (error) ERR syntax error). func (c cmdable) SetXX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd { var cmd *BoolCmd switch expiration { From b64f0876913578ac00c29d56a536ea2ec299c138 Mon Sep 17 00:00:00 2001 From: monkey92t Date: Fri, 25 Jun 2021 14:51:18 +0800 Subject: [PATCH 08/21] Adjust KeepTTL annotation. Signed-off-by: monkey92t --- commands.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/commands.go b/commands.go index 51a4ef8..9e1e5ad 100644 --- a/commands.go +++ b/commands.go @@ -9,8 +9,8 @@ import ( "github.com/go-redis/redis/v8/internal" ) -// KeepTTL is an option for Set command to keep key's existing TTL. -// It requires your redis-server version >= 6.0 (Otherwise you will receive an error: (error) ERR syntax error). +// KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0, +// otherwise you will receive an error: (error) ERR syntax error. // For example: // // rdb.Set(ctx, key, value, redis.KeepTTL) @@ -841,8 +841,8 @@ func (c cmdable) MSetNX(ctx context.Context, values ...interface{}) *BoolCmd { // Use expiration for `SETEX`-like behavior. // // Zero expiration means the key has no expiration time. -// KeepTTL(-1) expiration is a Redis KEEPTTL option to keep existing TTL. -// It requires your redis-server version >= 6.0 (Otherwise you will receive an error: (error) ERR syntax error). +// KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0, +// otherwise you will receive an error: (error) ERR syntax error. func (c cmdable) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd { args := make([]interface{}, 3, 5) args[0] = "set" @@ -875,8 +875,8 @@ type SetArgs struct { // 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. - // It requires your redis-server version >= 6.0 (Otherwise you will receive an error: (error) ERR syntax error). + // KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0, + // otherwise you will receive an error: (error) ERR syntax error. KeepTTL bool } @@ -924,8 +924,8 @@ func (c cmdable) SetEX(ctx context.Context, key string, value interface{}, expir // SetNX Redis `SET key value [expiration] NX` command. // // Zero expiration means the key has no expiration time. -// KeepTTL(-1) expiration is a Redis KEEPTTL option to keep existing TTL. -// It requires your redis-server version >= 6.0 (Otherwise you will receive an error: (error) ERR syntax error). +// KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0, +// otherwise you will receive an error: (error) ERR syntax error. func (c cmdable) SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd { var cmd *BoolCmd switch expiration { @@ -949,8 +949,8 @@ func (c cmdable) SetNX(ctx context.Context, key string, value interface{}, expir // SetXX Redis `SET key value [expiration] XX` command. // // Zero expiration means the key has no expiration time. -// KeepTTL(-1) expiration is a Redis KEEPTTL option to keep existing TTL. -// It requires your redis-server version >= 6.0 (Otherwise you will receive an error: (error) ERR syntax error). +// KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0, +// otherwise you will receive an error: (error) ERR syntax error. func (c cmdable) SetXX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd { var cmd *BoolCmd switch expiration { From 9cfca5827def4410970428388a51343632f9396e Mon Sep 17 00:00:00 2001 From: Vladimir Mihailenco Date: Mon, 28 Jun 2021 10:51:31 +0300 Subject: [PATCH 09/21] Tweak readme --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5f52a55..bc4624e 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,11 @@ - [Examples](https://pkg.go.dev/github.com/go-redis/redis/v8?tab=doc#pkg-examples) - [RealWorld example app](https://github.com/uptrace/go-treemux-realworld-example-app) -> :heart: Please check [Bun](https://bun.uptrace.dev) - fast and simple SQL client for PostgreSQL, -> MySQL, and SQLite. +My other projects: + +- [Bun](https://bun.uptrace.dev) - fast and simple SQL client for PostgreSQL, MySQL, and SQLite. +- [treemux](https://github.com/vmihailenco/treemux) - high-speed, flexible, tree-based HTTP router + for Go. ## Ecosystem From e757f789233b86de5593bc08701d9bb637a34343 Mon Sep 17 00:00:00 2001 From: Ali Josie <33804388+0xc0d@users.noreply.github.com> Date: Tue, 29 Jun 2021 04:23:07 +0200 Subject: [PATCH 10/21] Update to otel trace v1.0.0-RC1 (stable) and metric v0.21.0 (unstable) (#1802) --- extra/redisotel/example/go.mod | 8 +++++--- extra/redisotel/example/go.sum | 36 +++++++++++++++++++-------------- extra/redisotel/example/main.go | 4 ++-- extra/redisotel/go.mod | 4 ++-- go.mod | 2 +- go.sum | 20 ++++++++++++++++++ 6 files changed, 51 insertions(+), 23 deletions(-) diff --git a/extra/redisotel/example/go.mod b/extra/redisotel/example/go.mod index b621aab..1cbaf7f 100644 --- a/extra/redisotel/example/go.mod +++ b/extra/redisotel/example/go.mod @@ -4,7 +4,9 @@ go 1.16 require ( github.com/go-redis/redis/extra/redisotel/v8 v8.8.2 - go.opentelemetry.io/otel v0.19.0 - go.opentelemetry.io/otel/exporters/stdout v0.19.0 - go.opentelemetry.io/otel/sdk v0.19.0 + github.com/go-redis/redis/v8 v8.8.2 + go.opentelemetry.io/otel v1.0.0-RC1 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC1 + go.opentelemetry.io/otel/sdk v1.0.0-RC1 + go.opentelemetry.io/otel/sdk/metric v0.21.0 ) diff --git a/extra/redisotel/example/go.sum b/extra/redisotel/example/go.sum index 59284e5..4e05e03 100644 --- a/extra/redisotel/example/go.sum +++ b/extra/redisotel/example/go.sum @@ -1,5 +1,4 @@ -github.com/benbjohnson/clock v1.0.3 h1:vkLuvpK4fmtSCuo60+yC63p7y0BmQ8gm5ZXGuBCJyXg= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= @@ -27,8 +26,9 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -50,22 +50,28 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc 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.15.0/go.mod h1:e4GKElweB8W2gWUqbghw0B8t5MCTccc9212eNHnOHwA= -go.opentelemetry.io/otel v0.19.0 h1:Lenfy7QHRXPZVsw/12CWpxX6d/JkrX8wrx2vO8G80Ng= go.opentelemetry.io/otel v0.19.0/go.mod h1:j9bF567N9EfomkSidSfmMwIwIBuP37AMAIzVW85OxSg= -go.opentelemetry.io/otel/exporters/stdout v0.19.0 h1:6+QJvepCJ/YS3rOlsnjhVo527ohlPowOBgsZThR9Hoc= -go.opentelemetry.io/otel/exporters/stdout v0.19.0/go.mod h1:UI2JnNRaSt9ChIHkk4+uqieH27qKt9isV9e2qRorCtg= -go.opentelemetry.io/otel/metric v0.19.0 h1:dtZ1Ju44gkJkYvo+3qGqVXmf88tc+a42edOywypengg= +go.opentelemetry.io/otel v1.0.0-RC1 h1:4CeoX93DNTWt8awGK9JmNXzF9j7TyOu9upscEdtcdXc= +go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC1 h1:SEfJImgKQ5TP2aTJwN08qhS8oFlYWr/neECGsyuxKWg= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC1/go.mod h1:TAM/UYjVd1UdaifWkof3qj9cCW9oINemHfj0K6yodSo= +go.opentelemetry.io/otel/internal/metric v0.21.0 h1:gZlIBo5O51hZOOZz8vEcuRx/l5dnADadKfpT70AELoo= +go.opentelemetry.io/otel/internal/metric v0.21.0/go.mod h1:iOfAaY2YycsXfYD4kaRSbLx2LKmfpKObWBEv9QK5zFo= go.opentelemetry.io/otel/metric v0.19.0/go.mod h1:8f9fglJPRnXuskQmKpnad31lcLJ2VmNNqIsx/uIwBSc= -go.opentelemetry.io/otel/oteltest v0.19.0 h1:YVfA0ByROYqTwOxqHVZYZExzEpfZor+MU1rU+ip2v9Q= +go.opentelemetry.io/otel/metric v0.21.0 h1:ZtcJlHqVE4l8Su0WOLOd9fEPheJuYEiQ0wr9wv2p25I= +go.opentelemetry.io/otel/metric v0.21.0/go.mod h1:JWCt1bjivC4iCrz/aCrM1GSw+ZcvY44KCbaeeRhzHnc= go.opentelemetry.io/otel/oteltest v0.19.0/go.mod h1:tI4yxwh8U21v7JD6R3BcA/2+RBoTKFexE/PJ/nSO7IA= -go.opentelemetry.io/otel/sdk v0.19.0 h1:13pQquZyGbIvGxBWcVzUqe8kg5VGbTBiKKKXpYCylRM= -go.opentelemetry.io/otel/sdk v0.19.0/go.mod h1:ouO7auJYMivDjywCHA6bqTI7jJMVQV1HdKR5CmH8DGo= -go.opentelemetry.io/otel/sdk/export/metric v0.19.0 h1:9A1PC2graOx3epRLRWbq4DPCdpMUYK8XeCrdAg6ycbI= -go.opentelemetry.io/otel/sdk/export/metric v0.19.0/go.mod h1:exXalzlU6quLTXiv29J+Qpj/toOzL3H5WvpbbjouTBo= -go.opentelemetry.io/otel/sdk/metric v0.19.0 h1:fka1Zc/lpRMS+KlTP/TRXZuaFtSjUg/maHV3U8rt1Mc= -go.opentelemetry.io/otel/sdk/metric v0.19.0/go.mod h1:t12+Mqmj64q1vMpxHlCGXGggo0sadYxEG6U+Us/9OA4= -go.opentelemetry.io/otel/trace v0.19.0 h1:1ucYlenXIDA1OlHVLDZKX0ObXV5RLaq06DtUKz5e5zc= +go.opentelemetry.io/otel/oteltest v1.0.0-RC1 h1:G685iP3XiskCwk/z0eIabL55XUl2gk0cljhGk9sB0Yk= +go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= +go.opentelemetry.io/otel/sdk v1.0.0-RC1 h1:Sy2VLOOg24bipyC29PhuMXYNJrLsxkie8hyI7kUlG9Q= +go.opentelemetry.io/otel/sdk v1.0.0-RC1/go.mod h1:kj6yPn7Pgt5ByRuwesbaWcRLA+V7BSDg3Hf8xRvsvf8= +go.opentelemetry.io/otel/sdk/export/metric v0.21.0 h1:4tSMVkDbvrowOeP/6rOfGABEWv5n+0gCfhI/TWleUvc= +go.opentelemetry.io/otel/sdk/export/metric v0.21.0/go.mod h1:gTaOMSQmL4zfsTL47desIPbPla5MyMG29lN3PzcibVg= +go.opentelemetry.io/otel/sdk/metric v0.21.0 h1:LNLUj35NNdEpyJQwj/htiEsfnY6GeTIwYHweCJNV+nc= +go.opentelemetry.io/otel/sdk/metric v0.21.0/go.mod h1:OHOcF8ZjE/L8oL/QXpUFWklPwtaukrfHgoAiPek53rQ= go.opentelemetry.io/otel/trace v0.19.0/go.mod h1:4IXiNextNOpPnRlI4ryK69mn5iC84bjBWZQA5DXz/qg= +go.opentelemetry.io/otel/trace v1.0.0-RC1 h1:jrjqKJZEibFrDz+umEASeU3LvdVyWKlnTh7XEfwrT58= +go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= 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= diff --git a/extra/redisotel/example/main.go b/extra/redisotel/example/main.go index 8853ee0..335eb8f 100644 --- a/extra/redisotel/example/main.go +++ b/extra/redisotel/example/main.go @@ -6,14 +6,14 @@ import ( "github.com/go-redis/redis/extra/redisotel/v8" "github.com/go-redis/redis/v8" "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/exporters/stdout" + stdoutexporter "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" sdktrace "go.opentelemetry.io/otel/sdk/trace" ) var tracer = otel.Tracer("app_or_package_name") func main() { - exporter, err := stdout.NewExporter(stdout.WithPrettyPrint()) + exporter, err := stdoutexporter.New(stdoutexporter.WithPrettyPrint()) if err != nil { panic(err) } diff --git a/extra/redisotel/go.mod b/extra/redisotel/go.mod index 9e60138..28ba2d9 100644 --- a/extra/redisotel/go.mod +++ b/extra/redisotel/go.mod @@ -9,6 +9,6 @@ replace github.com/go-redis/redis/extra/rediscmd/v8 => ../rediscmd require ( github.com/go-redis/redis/extra/rediscmd/v8 v8.8.2 github.com/go-redis/redis/v8 v8.8.2 - go.opentelemetry.io/otel v0.20.0 - go.opentelemetry.io/otel/trace v0.20.0 + go.opentelemetry.io/otel v1.0.0-RC1 + go.opentelemetry.io/otel/trace v1.0.0-RC1 ) diff --git a/go.mod b/go.mod index aa13d2e..da281c2 100644 --- a/go.mod +++ b/go.mod @@ -7,5 +7,5 @@ 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/metric v0.20.0 + go.opentelemetry.io/otel/metric v0.21.0 ) diff --git a/go.sum b/go.sum index b830936..6334e9d 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,9 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -33,21 +36,35 @@ 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 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 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 h1:ruQGxdhGHe7FWOJPT0mKs5+pD2Xs1Bm/kdGlHO04FmM= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g= go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= +go.opentelemetry.io/otel v1.0.0-RC1 h1:4CeoX93DNTWt8awGK9JmNXzF9j7TyOu9upscEdtcdXc= +go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= +go.opentelemetry.io/otel/internal/metric v0.21.0 h1:gZlIBo5O51hZOOZz8vEcuRx/l5dnADadKfpT70AELoo= +go.opentelemetry.io/otel/internal/metric v0.21.0/go.mod h1:iOfAaY2YycsXfYD4kaRSbLx2LKmfpKObWBEv9QK5zFo= go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8= go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= +go.opentelemetry.io/otel/metric v0.21.0 h1:ZtcJlHqVE4l8Su0WOLOd9fEPheJuYEiQ0wr9wv2p25I= +go.opentelemetry.io/otel/metric v0.21.0/go.mod h1:JWCt1bjivC4iCrz/aCrM1GSw+ZcvY44KCbaeeRhzHnc= go.opentelemetry.io/otel/oteltest v0.20.0 h1:HiITxCawalo5vQzdHfKeZurV8x7ljcqAgiWzF6Vaeaw= go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= +go.opentelemetry.io/otel/oteltest v1.0.0-RC1 h1:G685iP3XiskCwk/z0eIabL55XUl2gk0cljhGk9sB0Yk= +go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw= go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= +go.opentelemetry.io/otel/trace v1.0.0-RC1 h1:jrjqKJZEibFrDz+umEASeU3LvdVyWKlnTh7XEfwrT58= +go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= 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 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -58,6 +75,7 @@ golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/Lt golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -74,6 +92,7 @@ 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= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e h1:4nW4NLDYnU28ojHaHO8OVxFHk/aQ33U01a9cjED+pzE= 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= @@ -89,6 +108,7 @@ google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyz google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= From b7d23d446cf61bc33d8346f929b814c0c8e7de5d Mon Sep 17 00:00:00 2001 From: Alexey Makhov Date: Tue, 29 Jun 2021 05:37:08 +0300 Subject: [PATCH 11/21] GOMAXPROCS usage instead of NumCPU (#1801) --- cluster.go | 2 +- options.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cluster.go b/cluster.go index e5d49dd..49b2d37 100644 --- a/cluster.go +++ b/cluster.go @@ -91,7 +91,7 @@ func (opt *ClusterOptions) init() { } if opt.PoolSize == 0 { - opt.PoolSize = 5 * runtime.NumCPU() + opt.PoolSize = 5 * runtime.GOMAXPROCS(0) } switch opt.ReadTimeout { diff --git a/options.go b/options.go index 7cf1bc1..8bbc27b 100644 --- a/options.go +++ b/options.go @@ -77,7 +77,7 @@ type Options struct { WriteTimeout time.Duration // Maximum number of socket connections. - // Default is 10 connections per every CPU as reported by runtime.NumCPU. + // Default is 10 connections per every available CPU as reported by runtime.GOMAXPROCS. PoolSize int // Minimum number of idle connections which is useful when establishing // new connection is slow. @@ -136,7 +136,7 @@ func (opt *Options) init() { } } if opt.PoolSize == 0 { - opt.PoolSize = 10 * runtime.NumCPU() + opt.PoolSize = 10 * runtime.GOMAXPROCS(0) } switch opt.ReadTimeout { case -1: From 27e2efb0af3a3f49582f3414b5291e7272041ecd Mon Sep 17 00:00:00 2001 From: Vladimir Mihailenco Date: Wed, 30 Jun 2021 13:40:23 +0300 Subject: [PATCH 12/21] Remove OpenTelemetry metrics for now (#1805) --- go.mod | 2 +- go.sum | 37 ------------------------------------- internal/instruments.go | 33 --------------------------------- internal/pool/conn.go | 9 +-------- internal/pool/pool.go | 1 - 5 files changed, 2 insertions(+), 80 deletions(-) delete mode 100644 internal/instruments.go diff --git a/go.mod b/go.mod index da281c2..c5ac426 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.13 require ( github.com/cespare/xxhash/v2 v2.1.1 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f + github.com/google/go-cmp v0.5.6 // indirect github.com/onsi/ginkgo v1.15.0 github.com/onsi/gomega v1.10.5 - go.opentelemetry.io/otel/metric v0.21.0 ) diff --git a/go.sum b/go.sum index 6334e9d..76abf5b 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,5 @@ github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -18,11 +16,8 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -34,37 +29,10 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= 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 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -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 h1:ruQGxdhGHe7FWOJPT0mKs5+pD2Xs1Bm/kdGlHO04FmM= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel v1.0.0-RC1 h1:4CeoX93DNTWt8awGK9JmNXzF9j7TyOu9upscEdtcdXc= -go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= -go.opentelemetry.io/otel/internal/metric v0.21.0 h1:gZlIBo5O51hZOOZz8vEcuRx/l5dnADadKfpT70AELoo= -go.opentelemetry.io/otel/internal/metric v0.21.0/go.mod h1:iOfAaY2YycsXfYD4kaRSbLx2LKmfpKObWBEv9QK5zFo= -go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/metric v0.21.0 h1:ZtcJlHqVE4l8Su0WOLOd9fEPheJuYEiQ0wr9wv2p25I= -go.opentelemetry.io/otel/metric v0.21.0/go.mod h1:JWCt1bjivC4iCrz/aCrM1GSw+ZcvY44KCbaeeRhzHnc= -go.opentelemetry.io/otel/oteltest v0.20.0 h1:HiITxCawalo5vQzdHfKeZurV8x7ljcqAgiWzF6Vaeaw= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/oteltest v1.0.0-RC1 h1:G685iP3XiskCwk/z0eIabL55XUl2gk0cljhGk9sB0Yk= -go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= -go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/otel/trace v1.0.0-RC1 h1:jrjqKJZEibFrDz+umEASeU3LvdVyWKlnTh7XEfwrT58= -go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= 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 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -75,7 +43,6 @@ golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/Lt golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -92,7 +59,6 @@ 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= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e h1:4nW4NLDYnU28ojHaHO8OVxFHk/aQ33U01a9cjED+pzE= 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= @@ -108,12 +74,9 @@ google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyz google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/instruments.go b/internal/instruments.go deleted file mode 100644 index 49d6111..0000000 --- a/internal/instruments.go +++ /dev/null @@ -1,33 +0,0 @@ -package internal - -import ( - "context" - - "go.opentelemetry.io/otel/metric" - "go.opentelemetry.io/otel/metric/global" -) - -var ( - // WritesCounter is a count of write commands performed. - WritesCounter metric.Int64Counter - // NewConnectionsCounter is a count of new connections. - NewConnectionsCounter metric.Int64Counter -) - -func init() { - defer func() { - if r := recover(); r != nil { - Logger.Printf(context.Background(), "Error creating meter github.com/go-redis/redis for Instruments", r) - } - }() - - meter := metric.Must(global.Meter("github.com/go-redis/redis")) - - WritesCounter = meter.NewInt64Counter("redis.writes", - metric.WithDescription("the number of writes initiated"), - ) - - NewConnectionsCounter = meter.NewInt64Counter("redis.new_connections", - metric.WithDescription("the number of connections created"), - ) -} diff --git a/internal/pool/conn.go b/internal/pool/conn.go index 1ce29ed..5661659 100644 --- a/internal/pool/conn.go +++ b/internal/pool/conn.go @@ -7,7 +7,6 @@ import ( "sync/atomic" "time" - "github.com/go-redis/redis/v8/internal" "github.com/go-redis/redis/v8/internal/proto" ) @@ -86,13 +85,7 @@ func (cn *Conn) WithWriter( return err } - if err := cn.bw.Flush(); err != nil { - return err - } - - internal.WritesCounter.Add(ctx, 1) - - return nil + return cn.bw.Flush() } func (cn *Conn) Close() error { diff --git a/internal/pool/pool.go b/internal/pool/pool.go index 4d247b3..a8f0a6d 100644 --- a/internal/pool/pool.go +++ b/internal/pool/pool.go @@ -188,7 +188,6 @@ func (p *ConnPool) dialConn(ctx context.Context, pooled bool) (*Conn, error) { return nil, err } - internal.NewConnectionsCounter.Add(ctx, 1) cn := NewConn(netConn) cn.pooled = pooled return cn, nil From dd4b7eb3b41c39c4f74ca016f09c55770df449c4 Mon Sep 17 00:00:00 2001 From: monkey Date: Wed, 30 Jun 2021 22:44:16 +0800 Subject: [PATCH 13/21] add release CHANGELOG Signed-off-by: monkey --- CHANGELOG.md | 5 +++++ commands.go | 2 ++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42d89b7..63aabd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ > :heart: > [**Uptrace.dev** - All-in-one tool to optimize performance and monitor errors & logs](https://uptrace.dev) +## v8.11 + +- Remove OpenTelemetry metrics. +- Supports more redis commands and options. + ## v8.10 - Removed extra OpenTelemetry spans from go-redis core. Now go-redis instrumentation only adds a diff --git a/commands.go b/commands.go index 9e1e5ad..d350b36 100644 --- a/commands.go +++ b/commands.go @@ -235,6 +235,8 @@ type Cmdable interface { XPendingExt(ctx context.Context, a *XPendingExtArgs) *XPendingExtCmd XClaim(ctx context.Context, a *XClaimArgs) *XMessageSliceCmd XClaimJustID(ctx context.Context, a *XClaimArgs) *StringSliceCmd + XAutoClaim(ctx context.Context, a *XAutoClaimArgs) *XAutoClaimCmd + XAutoClaimJustID(ctx context.Context, a *XAutoClaimArgs) *XAutoClaimJustIDCmd // TODO: XTrim and XTrimApprox remove in v9. XTrim(ctx context.Context, key string, maxLen int64) *IntCmd From c1b63a670345f9f41538ab1773c0e4d0be46c737 Mon Sep 17 00:00:00 2001 From: monkey92t Date: Mon, 5 Jul 2021 14:40:10 +0800 Subject: [PATCH 14/21] DBSize,ScriptLoad,ScriptFlush and ScriptExists should use hook (#1811) Signed-off-by: monkey --- cluster_commands.go | 102 ++++++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 46 deletions(-) diff --git a/cluster_commands.go b/cluster_commands.go index 336ea98..085bce8 100644 --- a/cluster_commands.go +++ b/cluster_commands.go @@ -8,55 +8,63 @@ import ( func (c *ClusterClient) DBSize(ctx context.Context) *IntCmd { cmd := NewIntCmd(ctx, "dbsize") - var size int64 - err := c.ForEachMaster(ctx, func(ctx context.Context, master *Client) error { - n, err := master.DBSize(ctx).Result() + _ = c.hooks.process(ctx, cmd, func(ctx context.Context, _ Cmder) error { + var size int64 + err := c.ForEachMaster(ctx, func(ctx context.Context, master *Client) error { + n, err := master.DBSize(ctx).Result() + if err != nil { + return err + } + atomic.AddInt64(&size, n) + return nil + }) if err != nil { - return err + cmd.SetErr(err) + } else { + cmd.val = size } - atomic.AddInt64(&size, n) return nil }) - if err != nil { - cmd.SetErr(err) - return cmd - } - cmd.val = size return cmd } func (c *ClusterClient) ScriptLoad(ctx context.Context, script string) *StringCmd { cmd := NewStringCmd(ctx, "script", "load", script) - mu := &sync.Mutex{} - err := c.ForEachShard(ctx, func(ctx context.Context, shard *Client) error { - val, err := shard.ScriptLoad(ctx, script).Result() + _ = c.hooks.process(ctx, cmd, func(ctx context.Context, _ Cmder) error { + mu := &sync.Mutex{} + err := c.ForEachShard(ctx, func(ctx context.Context, shard *Client) error { + val, err := shard.ScriptLoad(ctx, script).Result() + if err != nil { + return err + } + + mu.Lock() + if cmd.Val() == "" { + cmd.val = val + } + mu.Unlock() + + return nil + }) if err != nil { - return err + cmd.SetErr(err) } - - mu.Lock() - if cmd.Val() == "" { - cmd.val = val - } - mu.Unlock() - return nil }) - if err != nil { - cmd.SetErr(err) - } - return cmd } func (c *ClusterClient) ScriptFlush(ctx context.Context) *StatusCmd { cmd := NewStatusCmd(ctx, "script", "flush") - _ = c.ForEachShard(ctx, func(ctx context.Context, shard *Client) error { - shard.ScriptFlush(ctx) - + _ = c.hooks.process(ctx, cmd, func(ctx context.Context, _ Cmder) error { + err := c.ForEachShard(ctx, func(ctx context.Context, shard *Client) error { + return shard.ScriptFlush(ctx).Err() + }) + if err != nil { + cmd.SetErr(err) + } return nil }) - return cmd } @@ -74,26 +82,28 @@ func (c *ClusterClient) ScriptExists(ctx context.Context, hashes ...string) *Boo result[i] = true } - mu := &sync.Mutex{} - err := c.ForEachShard(ctx, func(ctx context.Context, shard *Client) error { - val, err := shard.ScriptExists(ctx, hashes...).Result() + _ = c.hooks.process(ctx, cmd, func(ctx context.Context, _ Cmder) error { + mu := &sync.Mutex{} + err := c.ForEachShard(ctx, func(ctx context.Context, shard *Client) error { + val, err := shard.ScriptExists(ctx, hashes...).Result() + if err != nil { + return err + } + + mu.Lock() + for i, v := range val { + result[i] = result[i] && v + } + mu.Unlock() + + return nil + }) if err != nil { - return err + cmd.SetErr(err) + } else { + cmd.val = result } - - mu.Lock() - for i, v := range val { - result[i] = result[i] && v - } - mu.Unlock() - return nil }) - if err != nil { - cmd.SetErr(err) - } - - cmd.val = result - return cmd } From 3caf52bceb25d68e5ad5a34fbe3347e42ba5ef30 Mon Sep 17 00:00:00 2001 From: monkey92t Date: Sun, 11 Jul 2021 18:27:48 +0800 Subject: [PATCH 15/21] Add the count option to the rpop command(fix #1813) (#1815) --- commands.go | 7 +++++++ commands_test.go | 14 ++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/commands.go b/commands.go index d350b36..8fd0397 100644 --- a/commands.go +++ b/commands.go @@ -190,6 +190,7 @@ type Cmdable interface { LSet(ctx context.Context, key string, index int64, value interface{}) *StatusCmd LTrim(ctx context.Context, key string, start, stop int64) *StatusCmd RPop(ctx context.Context, key string) *StringCmd + RPopCount(ctx context.Context, key string, count int) *StringSliceCmd RPopLPush(ctx context.Context, source, destination string) *StringCmd RPush(ctx context.Context, key string, values ...interface{}) *IntCmd RPushX(ctx context.Context, key string, values ...interface{}) *IntCmd @@ -1451,6 +1452,12 @@ func (c cmdable) RPop(ctx context.Context, key string) *StringCmd { return cmd } +func (c cmdable) RPopCount(ctx context.Context, key string, count int) *StringSliceCmd { + cmd := NewStringSliceCmd(ctx, "rpop", key, count) + _ = c(ctx, cmd) + return cmd +} + func (c cmdable) RPopLPush(ctx context.Context, source, destination string) *StringCmd { cmd := NewStringCmd(ctx, "rpoplpush", source, destination) _ = c(ctx, cmd) diff --git a/commands_test.go b/commands_test.go index 1557312..12f75cc 100644 --- a/commands_test.go +++ b/commands_test.go @@ -2268,6 +2268,20 @@ var _ = Describe("Commands", func() { Expect(lRange.Val()).To(Equal([]string{"one", "two"})) }) + It("should RPopCount", func() { + rPush := client.RPush(ctx, "list", "one", "two", "three", "four") + Expect(rPush.Err()).NotTo(HaveOccurred()) + Expect(rPush.Val()).To(Equal(int64(4))) + + rPopCount := client.RPopCount(ctx, "list", 2) + Expect(rPopCount.Err()).NotTo(HaveOccurred()) + Expect(rPopCount.Val()).To(Equal([]string{"four", "three"})) + + lRange := client.LRange(ctx, "list", 0, -1) + Expect(lRange.Err()).NotTo(HaveOccurred()) + Expect(lRange.Val()).To(Equal([]string{"one", "two"})) + }) + It("should RPopLPush", func() { rPush := client.RPush(ctx, "list", "one") Expect(rPush.Err()).NotTo(HaveOccurred()) From 247c62ad92711dd9721a59ad36c130ba92eee784 Mon Sep 17 00:00:00 2001 From: Vladimir Mihailenco Date: Wed, 14 Jul 2021 14:40:25 +0300 Subject: [PATCH 16/21] Add contributors --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index bc4624e..2c36f78 100644 --- a/README.md +++ b/README.md @@ -166,3 +166,11 @@ Lastly, run: ``` go test ``` + +## Contributors + +Thanks to all the people who already contributed! + + + + From ce40cd942a72c4a93f9025047e6fd3f510700ab3 Mon Sep 17 00:00:00 2001 From: ktaekwon000 Date: Fri, 16 Jul 2021 11:58:01 +0800 Subject: [PATCH 17/21] Allow FIFO pool in redis client (#1820) * Initial commit for FIFO pool * Change PoolType string to PoolFIFO bool * Remove redundant type * add PoolFIFO option to all clients Signed-off-by: monkey92t Co-authored-by: Kim Tae Kwon Co-authored-by: monkey92t --- cluster.go | 4 ++++ internal/pool/pool.go | 17 +++++++++++++---- options.go | 5 +++++ ring.go | 4 ++++ sentinel.go | 6 ++++++ universal.go | 6 ++++++ 6 files changed, 38 insertions(+), 4 deletions(-) diff --git a/cluster.go b/cluster.go index 49b2d37..9690f88 100644 --- a/cluster.go +++ b/cluster.go @@ -68,6 +68,9 @@ type ClusterOptions struct { ReadTimeout time.Duration WriteTimeout time.Duration + // PoolFIFO uses FIFO mode for each node connection pool GET/PUT (default LIFO). + PoolFIFO bool + // PoolSize applies per cluster node and not for the whole cluster. PoolSize int MinIdleConns int @@ -146,6 +149,7 @@ func (opt *ClusterOptions) clientOptions() *Options { ReadTimeout: opt.ReadTimeout, WriteTimeout: opt.WriteTimeout, + PoolFIFO: opt.PoolFIFO, PoolSize: opt.PoolSize, MinIdleConns: opt.MinIdleConns, MaxConnAge: opt.MaxConnAge, diff --git a/internal/pool/pool.go b/internal/pool/pool.go index a8f0a6d..91b55e4 100644 --- a/internal/pool/pool.go +++ b/internal/pool/pool.go @@ -57,6 +57,7 @@ type Options struct { Dialer func(context.Context) (net.Conn, error) OnClose func(*Conn) error + PoolFIFO bool PoolSize int MinIdleConns int MaxConnAge time.Duration @@ -308,13 +309,21 @@ func (p *ConnPool) freeTurn() { } func (p *ConnPool) popIdle() *Conn { - if len(p.idleConns) == 0 { + n := len(p.idleConns) + if n == 0 { return nil } - idx := len(p.idleConns) - 1 - cn := p.idleConns[idx] - p.idleConns = p.idleConns[:idx] + var cn *Conn + if p.opt.PoolFIFO { + cn = p.idleConns[0] + copy(p.idleConns, p.idleConns[1:]) + p.idleConns = p.idleConns[:n-1] + } else { + idx := n - 1 + cn = p.idleConns[idx] + p.idleConns = p.idleConns[:idx] + } p.idleConnsLen-- p.checkMinIdleConns() return cn diff --git a/options.go b/options.go index 8bbc27b..5d39bf0 100644 --- a/options.go +++ b/options.go @@ -76,6 +76,10 @@ type Options struct { // Default is ReadTimeout. WriteTimeout time.Duration + // Type of connection pool. + // true for FIFO pool, false for LIFO pool. + // Note that fifo has higher overhead compared to lifo. + PoolFIFO bool // Maximum number of socket connections. // Default is 10 connections per every available CPU as reported by runtime.GOMAXPROCS. PoolSize int @@ -291,6 +295,7 @@ func newConnPool(opt *Options) *pool.ConnPool { Dialer: func(ctx context.Context) (net.Conn, error) { return opt.Dialer(ctx, opt.Network, opt.Addr) }, + PoolFIFO: opt.PoolFIFO, PoolSize: opt.PoolSize, MinIdleConns: opt.MinIdleConns, MaxConnAge: opt.MaxConnAge, diff --git a/ring.go b/ring.go index 34d05f3..5e35b6b 100644 --- a/ring.go +++ b/ring.go @@ -78,6 +78,9 @@ type RingOptions struct { ReadTimeout time.Duration WriteTimeout time.Duration + // PoolFIFO uses FIFO mode for each node connection pool GET/PUT (default LIFO). + PoolFIFO bool + PoolSize int MinIdleConns int MaxConnAge time.Duration @@ -138,6 +141,7 @@ func (opt *RingOptions) clientOptions() *Options { ReadTimeout: opt.ReadTimeout, WriteTimeout: opt.WriteTimeout, + PoolFIFO: opt.PoolFIFO, PoolSize: opt.PoolSize, MinIdleConns: opt.MinIdleConns, MaxConnAge: opt.MaxConnAge, diff --git a/sentinel.go b/sentinel.go index ca2e088..7b53fd4 100644 --- a/sentinel.go +++ b/sentinel.go @@ -57,6 +57,9 @@ type FailoverOptions struct { ReadTimeout time.Duration WriteTimeout time.Duration + // PoolFIFO uses FIFO mode for each node connection pool GET/PUT (default LIFO). + PoolFIFO bool + PoolSize int MinIdleConns int MaxConnAge time.Duration @@ -86,6 +89,7 @@ func (opt *FailoverOptions) clientOptions() *Options { ReadTimeout: opt.ReadTimeout, WriteTimeout: opt.WriteTimeout, + PoolFIFO: opt.PoolFIFO, PoolSize: opt.PoolSize, PoolTimeout: opt.PoolTimeout, IdleTimeout: opt.IdleTimeout, @@ -115,6 +119,7 @@ func (opt *FailoverOptions) sentinelOptions(addr string) *Options { ReadTimeout: opt.ReadTimeout, WriteTimeout: opt.WriteTimeout, + PoolFIFO: opt.PoolFIFO, PoolSize: opt.PoolSize, PoolTimeout: opt.PoolTimeout, IdleTimeout: opt.IdleTimeout, @@ -146,6 +151,7 @@ func (opt *FailoverOptions) clusterOptions() *ClusterOptions { ReadTimeout: opt.ReadTimeout, WriteTimeout: opt.WriteTimeout, + PoolFIFO: opt.PoolFIFO, PoolSize: opt.PoolSize, PoolTimeout: opt.PoolTimeout, IdleTimeout: opt.IdleTimeout, diff --git a/universal.go b/universal.go index bb5f8b6..1e962ab 100644 --- a/universal.go +++ b/universal.go @@ -35,6 +35,9 @@ type UniversalOptions struct { ReadTimeout time.Duration WriteTimeout time.Duration + // PoolFIFO uses FIFO mode for each node connection pool GET/PUT (default LIFO). + PoolFIFO bool + PoolSize int MinIdleConns int MaxConnAge time.Duration @@ -83,6 +86,7 @@ func (o *UniversalOptions) Cluster() *ClusterOptions { DialTimeout: o.DialTimeout, ReadTimeout: o.ReadTimeout, WriteTimeout: o.WriteTimeout, + PoolFIFO: o.PoolFIFO, PoolSize: o.PoolSize, MinIdleConns: o.MinIdleConns, MaxConnAge: o.MaxConnAge, @@ -120,6 +124,7 @@ func (o *UniversalOptions) Failover() *FailoverOptions { ReadTimeout: o.ReadTimeout, WriteTimeout: o.WriteTimeout, + PoolFIFO: o.PoolFIFO, PoolSize: o.PoolSize, MinIdleConns: o.MinIdleConns, MaxConnAge: o.MaxConnAge, @@ -155,6 +160,7 @@ func (o *UniversalOptions) Simple() *Options { ReadTimeout: o.ReadTimeout, WriteTimeout: o.WriteTimeout, + PoolFIFO: o.PoolFIFO, PoolSize: o.PoolSize, MinIdleConns: o.MinIdleConns, MaxConnAge: o.MaxConnAge, From 62fc2c821b7b9d757a5dee74a4c17e0010c8301e Mon Sep 17 00:00:00 2001 From: Anatoly Rugalev Date: Sat, 17 Jul 2021 18:20:48 +0200 Subject: [PATCH 18/21] Check Failing() before serving random node (#1825) * Check Failing() before serving random node * Revert condition * Addressed review comments * Fallback to random failing node --- cluster.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cluster.go b/cluster.go index 9690f88..8d93b36 100644 --- a/cluster.go +++ b/cluster.go @@ -595,8 +595,16 @@ func (c *clusterState) slotRandomNode(slot int) (*clusterNode, error) { if len(nodes) == 0 { return c.nodes.Random() } - n := rand.Intn(len(nodes)) - return nodes[n], nil + if len(nodes) == 1 { + return nodes[0], nil + } + randomNodes := rand.Perm(len(nodes)) + for _, idx := range randomNodes { + if node := nodes[idx]; !node.Failing() { + return node, nil + } + } + return nodes[randomNodes[0]], nil } func (c *clusterState) slotNodes(slot int) []*clusterNode { From 346bfafddd36dd52d51b064033048de5552ee91e Mon Sep 17 00:00:00 2001 From: do it Date: Tue, 20 Jul 2021 17:23:48 +0800 Subject: [PATCH 19/21] ConnPool check fd for bad conns (#1824) * conncheck for badconn (#1821) * format imports * fix ut: pool with badconn * fix unstable ut: should facilitate failover * Revert "fix unstable ut: should facilitate failover" This reverts commit c7eeca2a5ca7cdef82cfe39b21dd781d5a286007. * fix test error Signed-off-by: monkey92t Co-authored-by: hidu Co-authored-by: monkey92t --- internal/pool/conncheck.go | 45 +++++++++++++++++ internal/pool/conncheck_dummy.go | 9 ++++ internal/pool/conncheck_test.go | 46 +++++++++++++++++ internal/pool/main_test.go | 87 +++++++++++++++++++++++++++++++- internal/pool/pool.go | 4 +- internal/pool/pool_test.go | 7 ++- main_test.go | 10 ++-- pool_test.go | 3 +- sentinel_test.go | 2 +- tx_test.go | 9 ++-- 10 files changed, 204 insertions(+), 18 deletions(-) create mode 100644 internal/pool/conncheck.go create mode 100644 internal/pool/conncheck_dummy.go create mode 100644 internal/pool/conncheck_test.go diff --git a/internal/pool/conncheck.go b/internal/pool/conncheck.go new file mode 100644 index 0000000..5dd60df --- /dev/null +++ b/internal/pool/conncheck.go @@ -0,0 +1,45 @@ +// +build linux darwin dragonfly freebsd netbsd openbsd solaris illumos + +package pool + +import ( + "errors" + "io" + "net" + "syscall" +) + +var errUnexpectedRead = errors.New("unexpected read from socket") + +func connCheck(conn net.Conn) error { + sysConn, ok := conn.(syscall.Conn) + if !ok { + return nil + } + rawConn, err := sysConn.SyscallConn() + if err != nil { + return err + } + + var sysErr error + err = rawConn.Read(func(fd uintptr) bool { + var buf [1]byte + n, err := syscall.Read(int(fd), buf[:]) + switch { + case n == 0 && err == nil: + sysErr = io.EOF + case n > 0: + sysErr = errUnexpectedRead + case err == syscall.EAGAIN || err == syscall.EWOULDBLOCK: + sysErr = nil + default: + sysErr = err + } + return true + }) + if err != nil { + return err + } + + return sysErr +} diff --git a/internal/pool/conncheck_dummy.go b/internal/pool/conncheck_dummy.go new file mode 100644 index 0000000..1daf986 --- /dev/null +++ b/internal/pool/conncheck_dummy.go @@ -0,0 +1,9 @@ +// +build !linux,!darwin,!dragonfly,!freebsd,!netbsd,!openbsd,!solaris,!illumos + +package pool + +import "net" + +func connCheck(conn net.Conn) error { + return nil +} diff --git a/internal/pool/conncheck_test.go b/internal/pool/conncheck_test.go new file mode 100644 index 0000000..0332174 --- /dev/null +++ b/internal/pool/conncheck_test.go @@ -0,0 +1,46 @@ +// +build linux darwin dragonfly freebsd netbsd openbsd solaris illumos + +package pool + +import ( + "net" + "net/http/httptest" + "testing" + "time" +) + +func Test_connCheck(t *testing.T) { + // tests with real conns + ts := httptest.NewServer(nil) + defer ts.Close() + + t.Run("good conn", func(t *testing.T) { + conn, err := net.DialTimeout(ts.Listener.Addr().Network(), ts.Listener.Addr().String(), time.Second) + if err != nil { + t.Fatalf(err.Error()) + } + defer conn.Close() + if err = connCheck(conn); err != nil { + t.Fatalf(err.Error()) + } + conn.Close() + + if err = connCheck(conn); err == nil { + t.Fatalf("expect has error") + } + }) + + t.Run("bad conn 2", func(t *testing.T) { + conn, err := net.DialTimeout(ts.Listener.Addr().Network(), ts.Listener.Addr().String(), time.Second) + if err != nil { + t.Fatalf(err.Error()) + } + defer conn.Close() + + ts.Close() + + if err = connCheck(conn); err == nil { + t.Fatalf("expect has err") + } + }) +} diff --git a/internal/pool/main_test.go b/internal/pool/main_test.go index 2365dbc..c54a38d 100644 --- a/internal/pool/main_test.go +++ b/internal/pool/main_test.go @@ -2,9 +2,12 @@ package pool_test import ( "context" + "fmt" "net" "sync" + "syscall" "testing" + "time" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -32,5 +35,87 @@ func perform(n int, cbs ...func(int)) { } func dummyDialer(context.Context) (net.Conn, error) { - return &net.TCPConn{}, nil + // return &net.TCPConn{}, nil + return newDummyConn(), nil +} + +func newDummyConn() net.Conn { + return &dummyConn{ + rawConn: &dummyRawConn{}, + } +} + +var _ net.Conn = (*dummyConn)(nil) +var _ syscall.Conn = (*dummyConn)(nil) + +type dummyConn struct { + rawConn *dummyRawConn +} + +func (d *dummyConn) SyscallConn() (syscall.RawConn, error) { + return d.rawConn, nil +} + +var errDummy = fmt.Errorf("dummyConn err") + +func (d *dummyConn) Read(b []byte) (n int, err error) { + return 0, errDummy +} + +func (d *dummyConn) Write(b []byte) (n int, err error) { + return 0, errDummy +} + +func (d *dummyConn) Close() error { + d.rawConn.Close() + return nil +} + +func (d *dummyConn) LocalAddr() net.Addr { + return &net.TCPAddr{} +} + +func (d *dummyConn) RemoteAddr() net.Addr { + return &net.TCPAddr{} +} + +func (d *dummyConn) SetDeadline(t time.Time) error { + return nil +} + +func (d *dummyConn) SetReadDeadline(t time.Time) error { + return nil +} + +func (d *dummyConn) SetWriteDeadline(t time.Time) error { + return nil +} + +var _ syscall.RawConn = (*dummyRawConn)(nil) + +type dummyRawConn struct { + closed bool + mux sync.Mutex +} + +func (d *dummyRawConn) Control(f func(fd uintptr)) error { + return nil +} + +func (d *dummyRawConn) Read(f func(fd uintptr) (done bool)) error { + d.mux.Lock() + defer d.mux.Unlock() + if d.closed { + return fmt.Errorf("dummyRawConn closed") + } + return nil +} + +func (d *dummyRawConn) Write(f func(fd uintptr) (done bool)) error { + return nil +} +func (d *dummyRawConn) Close() { + d.mux.Lock() + d.closed = true + d.mux.Unlock() } diff --git a/internal/pool/pool.go b/internal/pool/pool.go index 91b55e4..577923a 100644 --- a/internal/pool/pool.go +++ b/internal/pool/pool.go @@ -520,7 +520,7 @@ func (p *ConnPool) reapStaleConn() *Conn { func (p *ConnPool) isStaleConn(cn *Conn) bool { if p.opt.IdleTimeout == 0 && p.opt.MaxConnAge == 0 { - return false + return connCheck(cn.netConn) != nil } now := time.Now() @@ -531,5 +531,5 @@ func (p *ConnPool) isStaleConn(cn *Conn) bool { return true } - return false + return connCheck(cn.netConn) != nil } diff --git a/internal/pool/pool_test.go b/internal/pool/pool_test.go index 795aef3..6c94fc2 100644 --- a/internal/pool/pool_test.go +++ b/internal/pool/pool_test.go @@ -6,10 +6,10 @@ import ( "testing" "time" - "github.com/go-redis/redis/v8/internal/pool" - . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + + "github.com/go-redis/redis/v8/internal/pool" ) var _ = Describe("ConnPool", func() { @@ -285,6 +285,8 @@ var _ = Describe("conns reaper", func() { cn.SetUsedAt(time.Now().Add(-2 * idleTimeout)) case "aged": cn.SetCreatedAt(time.Now().Add(-2 * maxAge)) + case "conncheck": + cn.Close() } conns = append(conns, cn) staleConns = append(staleConns, cn) @@ -371,6 +373,7 @@ var _ = Describe("conns reaper", func() { assert("idle") assert("aged") + assert("conncheck") }) var _ = Describe("race", func() { diff --git a/main_test.go b/main_test.go index 0cb2b1d..dd9d874 100644 --- a/main_test.go +++ b/main_test.go @@ -12,10 +12,10 @@ import ( "testing" "time" - "github.com/go-redis/redis/v8" - . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + + "github.com/go-redis/redis/v8" ) const ( @@ -117,7 +117,7 @@ func TestGinkgoSuite(t *testing.T) { RunSpecs(t, "go-redis") } -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ func redisOptions() *redis.Options { return &redis.Options{ @@ -364,7 +364,7 @@ func startSentinel(port, masterName, masterPort string) (*redisProcess, error) { return p, nil } -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ type badConnError string @@ -409,7 +409,7 @@ func (cn *badConn) Write([]byte) (int, error) { return 0, badConnError("bad connection") } -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ type hook struct { beforeProcess func(ctx context.Context, cmd redis.Cmder) (context.Context, error) diff --git a/pool_test.go b/pool_test.go index 08acc6d..8131819 100644 --- a/pool_test.go +++ b/pool_test.go @@ -87,8 +87,9 @@ var _ = Describe("pool", func() { cn.SetNetConn(&badConn{}) client.Pool().Put(ctx, cn) + // connCheck will automatically remove damaged connections. err = client.Ping(ctx).Err() - Expect(err).To(MatchError("bad connection")) + Expect(err).NotTo(HaveOccurred()) val, err := client.Ping(ctx).Result() Expect(err).NotTo(HaveOccurred()) diff --git a/sentinel_test.go b/sentinel_test.go index 7b4aabd..5faf9cf 100644 --- a/sentinel_test.go +++ b/sentinel_test.go @@ -191,7 +191,7 @@ var _ = Describe("NewFailoverClusterClient", func() { err = master.Shutdown(ctx).Err() Expect(err).NotTo(HaveOccurred()) Eventually(func() error { - return sentinelMaster.Ping(ctx).Err() + return master.Ping(ctx).Err() }, "15s", "100ms").Should(HaveOccurred()) // Check that client picked up new master. diff --git a/tx_test.go b/tx_test.go index 4681122..11e5b0d 100644 --- a/tx_test.go +++ b/tx_test.go @@ -123,7 +123,7 @@ var _ = Describe("Tx", func() { Expect(num).To(Equal(int64(N))) }) - It("should recover from bad connection", func() { + It("should remove from bad connection", func() { // Put bad connection in the pool. cn, err := client.Pool().Get(context.Background()) Expect(err).NotTo(HaveOccurred()) @@ -134,17 +134,14 @@ var _ = Describe("Tx", func() { do := func() error { err := client.Watch(ctx, func(tx *redis.Tx) error { _, err := tx.TxPipelined(ctx, func(pipe redis.Pipeliner) error { - pipe.Ping(ctx) - return nil + return pipe.Ping(ctx).Err() }) return err }) return err } - err = do() - Expect(err).To(MatchError("bad connection")) - + // connCheck will automatically remove damaged connections. err = do() Expect(err).NotTo(HaveOccurred()) }) From 54ef62f9b700cacd0f6262b8ca182b192d15dd38 Mon Sep 17 00:00:00 2001 From: Matthieu MOREL Date: Thu, 22 Jul 2021 04:26:33 +0200 Subject: [PATCH 20/21] Create dependabot.yml (#1826) --- .github/dependabot.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..77b7be5 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: +- package-ecosystem: gomod + directory: / + schedule: + interval: weekly +- package-ecosystem: github-actions + directory: / + schedule: + interval: weekly From 704212eaaebb131b3edfd20beb6b4e81c575b39e Mon Sep 17 00:00:00 2001 From: MengZeLee Date: Thu, 22 Jul 2021 10:27:46 +0800 Subject: [PATCH 21/21] fix typo (#1829) --- example_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example_test.go b/example_test.go index 7d9f740..7977bf9 100644 --- a/example_test.go +++ b/example_test.go @@ -417,7 +417,7 @@ func ExampleClient_Watch() { // Actual opperation (local in optimistic lock). n++ - // Operation is commited only if the watched keys remain unchanged. + // Operation is committed only if the watched keys remain unchanged. _, err = tx.TxPipelined(ctx, func(pipe redis.Pipeliner) error { pipe.Set(ctx, key, n, 0) return nil