From ee0a6d329a53dacfb7e494d87e0aaf07bf60d061 Mon Sep 17 00:00:00 2001 From: Yann Hamon Date: Wed, 27 Dec 2023 13:03:25 +0100 Subject: [PATCH] Update deps (#48) * Update dependencies --- Dockerfile-alpine | 4 +- Makefile | 12 +- go.mod | 6 +- go.sum | 7 +- .../mediocregopher/radix/v3/CHANGELOG.md | 10 ++ .../mediocregopher/radix/v3/README.md | 4 + .../mediocregopher/radix/v3/cluster.go | 25 +++- .../mediocregopher/radix/v3/cluster_topo.go | 55 +++++-- vendor/golang.org/x/xerrors/doc.go | 3 +- vendor/golang.org/x/xerrors/fmt.go | 141 ++++++++++++++---- vendor/golang.org/x/xerrors/wrap.go | 6 + vendor/modules.txt | 6 +- 12 files changed, 214 insertions(+), 65 deletions(-) diff --git a/Dockerfile-alpine b/Dockerfile-alpine index b966e1f..a1aff5a 100644 --- a/Dockerfile-alpine +++ b/Dockerfile-alpine @@ -1,5 +1,5 @@ -FROM alpine:3.15 +FROM alpine:3.19 MAINTAINER Yann HAMON RUN apk add ca-certificates COPY redis-dump-go / -ENTRYPOINT ["/redis-dump-go"] \ No newline at end of file +ENTRYPOINT ["/redis-dump-go"] diff --git a/Makefile b/Makefile index 5e3da4c..09b9b0e 100644 --- a/Makefile +++ b/Makefile @@ -16,9 +16,11 @@ build: go build -o bin/redis-dump-go build-static: + git config --global --add safe.directory $$PWD CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o bin/redis-dump-go build-generator-static: + git config --global --add safe.directory $$PWD CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o bin/generator ./utils/generator/main.go docker-image: @@ -32,20 +34,20 @@ push-image: docker push ghcr.io/yannh/redis-dump-go:${RELEASE_VERSION} docker-test: - docker run -t -v $$PWD:/go/src/github.com/yannh/redis-dump-go -w /go/src/github.com/yannh/redis-dump-go golang:1.18 make test + docker run -t -v $$PWD:/go/src/github.com/yannh/redis-dump-go -w /go/src/github.com/yannh/redis-dump-go golang:1.21 make test docker-build-static: - docker run -t -v $$PWD:/go/src/github.com/yannh/redis-dump-go -w /go/src/github.com/yannh/redis-dump-go golang:1.18 make build-static + docker run -t -v $$PWD:/go/src/github.com/yannh/redis-dump-go -w /go/src/github.com/yannh/redis-dump-go golang:1.21 make build-static docker-build-generator-static: - docker run -t -v $$PWD:/go/src/github.com/yannh/redis-dump-go -w /go/src/github.com/yannh/redis-dump-go golang:1.18 make build-generator-static + docker run -t -v $$PWD:/go/src/github.com/yannh/redis-dump-go -w /go/src/github.com/yannh/redis-dump-go golang:1.21 make build-generator-static goreleaser-build-static: - docker run -e GOCACHE=/tmp -v $$PWD/.gitconfig:/root/.gitconfig -t -v $$PWD:/go/src/github.com/yannh/redis-dump-go -w /go/src/github.com/yannh/redis-dump-go goreleaser/goreleaser:v1.8.3 build --single-target --skip-post-hooks --rm-dist --snapshot + docker run -t -e GOOS=linux -e GOARCH=amd64 -v $$PWD:/go/src/github.com/yannh/redis-dump-go -w /go/src/github.com/yannh/redis-dump-go goreleaser/goreleaser:v1.22.1 build --single-target --skip-post-hooks --rm-dist --snapshot cp dist/redis-dump-go_linux_amd64_v1/redis-dump-go bin/ release: - docker run -e GITHUB_TOKEN -t -v $$PWD/.gitconfig:/root/.gitconfig -v /var/run/docker.sock:/var/run/docker.sock -v $$PWD:/go/src/github.com/yannh/redis-dump-go -w /go/src/github.com/yannh/redis-dump-go goreleaser/goreleaser:v1.8.3 release --rm-dist + docker run -e GITHUB_TOKEN -e GIT_OWNER -t -v /var/run/docker.sock:/var/run/docker.sock -v $$PWD:/go/src/github.com/yannh/redis-dump-go -w /go/src/github.com/yannh/redis-dump-go goreleaser/goreleaser:v1.22.1 release --rm-dist acceptance-tests: docker-build-static docker-build-generator-static docker-compose run tests diff --git a/go.mod b/go.mod index 8cab39e..ac339c6 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/yannh/redis-dump-go -go 1.18 +go 1.21 -require github.com/mediocregopher/radix/v3 v3.8.0 +require github.com/mediocregopher/radix/v3 v3.8.1 -require golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 // indirect +require golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect diff --git a/go.sum b/go.sum index 8eb6d03..680320a 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/mediocregopher/radix/v3 v3.8.0 h1:HI8EgkaM7WzsrFpYAkOXIgUKbjNonb2Ne7K6Le61Pmg= -github.com/mediocregopher/radix/v3 v3.8.0/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/mediocregopher/radix/v3 v3.8.1 h1:rOkHflVuulFKlwsLY01/M2cM2tWCjDoETcMqKbAWu1M= +github.com/mediocregopher/radix/v3 v3.8.1/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= 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/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= diff --git a/vendor/github.com/mediocregopher/radix/v3/CHANGELOG.md b/vendor/github.com/mediocregopher/radix/v3/CHANGELOG.md index 1a04e28..642fbe6 100644 --- a/vendor/github.com/mediocregopher/radix/v3/CHANGELOG.md +++ b/vendor/github.com/mediocregopher/radix/v3/CHANGELOG.md @@ -1,5 +1,15 @@ Changelog from v3.0.1 and up. Prior changes don't have a changelog. +# v3.8.1 + +* Fixed `NewCluster` not returning an error if it can't connect to any of the + redis instances given. (#319) + +* Fix deadlock in `Cluster` when using `DoSecondary`. (#317) + +* Fix parsing for `CLUSTER SLOTS` command, which changed slightly with redis + 7.0. (#322) + # v3.8.0 **New** diff --git a/vendor/github.com/mediocregopher/radix/v3/README.md b/vendor/github.com/mediocregopher/radix/v3/README.md index 4ad0763..588398d 100644 --- a/vendor/github.com/mediocregopher/radix/v3/README.md +++ b/vendor/github.com/mediocregopher/radix/v3/README.md @@ -7,6 +7,10 @@ below for documentation and general usage examples. **[v4 Documentation](https://pkg.go.dev/github.com/mediocregopher/radix/v4#section-documentation)** +**[Discussion/Support Chat](https://matrix.to/#/#radix:waffle.farm)** + +Please open an issue, or start a discussion in the chat, before opening a pull request! + ## Features * Standard print-like API which supports **all current and future redis commands**. diff --git a/vendor/github.com/mediocregopher/radix/v3/cluster.go b/vendor/github.com/mediocregopher/radix/v3/cluster.go index 5c47271..7de66a5 100644 --- a/vendor/github.com/mediocregopher/radix/v3/cluster.go +++ b/vendor/github.com/mediocregopher/radix/v3/cluster.go @@ -201,16 +201,24 @@ func NewCluster(clusterAddrs []string, opts ...ClusterOpt) (*Cluster, error) { } } + var err error + // make a pool to base the cluster on for _, addr := range clusterAddrs { - p, err := c.co.pf("tcp", addr) - if err != nil { + + var p Client + + if p, err = c.co.pf("tcp", addr); err != nil { continue } c.pools[addr] = p break } + if len(c.pools) == 0 { + return nil, fmt.Errorf("could not connect to any redis instances, last error was: %w", err) + } + p, err := c.pool("") if err != nil { for _, p := range c.pools { @@ -486,10 +494,9 @@ func (c *Cluster) syncEvery(d time.Duration) { }() } -func (c *Cluster) addrForKey(key string) string { +// v3.8.5 add the getting master node without lock to fix the fix deadlock. +func (c *Cluster) addrForKeyWithNoLock(key string) string { s := ClusterSlot([]byte(key)) - c.l.RLock() - defer c.l.RUnlock() for _, t := range c.primTopo { for _, slot := range t.Slots { if s >= slot[0] && s < slot[1] { @@ -500,10 +507,16 @@ func (c *Cluster) addrForKey(key string) string { return "" } +func (c *Cluster) addrForKey(key string) string { + c.l.RLock() + defer c.l.RUnlock() + return c.addrForKeyWithNoLock(key) +} + func (c *Cluster) secondaryAddrForKey(key string) string { c.l.RLock() defer c.l.RUnlock() - primAddr := c.addrForKey(key) + primAddr := c.addrForKeyWithNoLock(key) for addr := range c.secondaries[primAddr] { return addr } diff --git a/vendor/github.com/mediocregopher/radix/v3/cluster_topo.go b/vendor/github.com/mediocregopher/radix/v3/cluster_topo.go index b105a0a..9398889 100644 --- a/vendor/github.com/mediocregopher/radix/v3/cluster_topo.go +++ b/vendor/github.com/mediocregopher/radix/v3/cluster_topo.go @@ -6,6 +6,7 @@ import ( "io" "net" "sort" + "strconv" "github.com/mediocregopher/radix/v3/resp" "github.com/mediocregopher/radix/v3/resp/resp2" @@ -157,8 +158,15 @@ func (tss topoSlotSet) MarshalRESP(w io.Writer) error { marshal(resp2.Any{I: tss.slots[1] - 1}) for _, n := range tss.nodes { - host, port, _ := net.SplitHostPort(n.Addr) - node := []string{host, port} + + host, portStr, _ := net.SplitHostPort(n.Addr) + + port, err := strconv.Atoi(portStr) + if err != nil { + return err + } + + node := []interface{}{host, port} if n.ID != "" { node = append(node, n.ID) } @@ -186,21 +194,44 @@ func (tss *topoSlotSet) UnmarshalRESP(br *bufio.Reader) error { var primaryNode ClusterNode for i := 0; i < arrHead.N; i++ { - var nodeStrs []string - if err := (resp2.Any{I: &nodeStrs}).UnmarshalRESP(br); err != nil { + + var nodeArrHead resp2.ArrayHeader + if err := nodeArrHead.UnmarshalRESP(br); err != nil { + return err + } else if nodeArrHead.N < 2 { + return fmt.Errorf("expected at least 2 array elements, got %d", nodeArrHead.N) + } + + var ip resp2.BulkString + if err := ip.UnmarshalRESP(br); err != nil { return err - } else if len(nodeStrs) < 2 { - return fmt.Errorf("malformed node array: %#v", nodeStrs) } - ip, port := nodeStrs[0], nodeStrs[1] - var id string - if len(nodeStrs) > 2 { - id = nodeStrs[2] + + var port resp2.Int + if err := port.UnmarshalRESP(br); err != nil { + return err + } + + nodeArrHead.N -= 2 + + var id resp2.BulkString + if nodeArrHead.N > 0 { + if err := id.UnmarshalRESP(br); err != nil { + return err + } + nodeArrHead.N-- + } + + // discard anything after + for i := 0; i < nodeArrHead.N; i++ { + if err := (resp2.Any{}).UnmarshalRESP(br); err != nil { + return err + } } node := ClusterNode{ - Addr: net.JoinHostPort(ip, port), - ID: id, + Addr: net.JoinHostPort(ip.S, strconv.FormatInt(port.I, 10)), + ID: id.S, Slots: [][2]uint16{tss.slots}, } diff --git a/vendor/golang.org/x/xerrors/doc.go b/vendor/golang.org/x/xerrors/doc.go index eef99d9..2ef99f5 100644 --- a/vendor/golang.org/x/xerrors/doc.go +++ b/vendor/golang.org/x/xerrors/doc.go @@ -5,7 +5,8 @@ // Package xerrors implements functions to manipulate errors. // // This package is based on the Go 2 proposal for error values: -// https://golang.org/design/29934-error-values +// +// https://golang.org/design/29934-error-values // // These functions were incorporated into the standard library's errors package // in Go 1.13: diff --git a/vendor/golang.org/x/xerrors/fmt.go b/vendor/golang.org/x/xerrors/fmt.go index 74c1c93..27a5d70 100644 --- a/vendor/golang.org/x/xerrors/fmt.go +++ b/vendor/golang.org/x/xerrors/fmt.go @@ -7,10 +7,14 @@ package xerrors import ( "fmt" "strings" + "unicode" + "unicode/utf8" "golang.org/x/xerrors/internal" ) +const percentBangString = "%!" + // Errorf formats according to a format specifier and returns the string as a // value that satisfies error. // @@ -18,29 +22,74 @@ import ( // formatted with additional detail enabled. If the last argument is an error // the returned error's Format method will return it if the format string ends // with ": %s", ": %v", or ": %w". If the last argument is an error and the -// format string ends with ": %w", the returned error implements Wrapper -// with an Unwrap method returning it. +// format string ends with ": %w", the returned error implements an Unwrap +// method returning it. +// +// If the format specifier includes a %w verb with an error operand in a +// position other than at the end, the returned error will still implement an +// Unwrap method returning the operand, but the error's Format method will not +// return the wrapped error. +// +// It is invalid to include more than one %w verb or to supply it with an +// operand that does not implement the error interface. The %w verb is otherwise +// a synonym for %v. +// +// Note that as of Go 1.13, the fmt.Errorf function will do error formatting, +// but it will not capture a stack backtrace. func Errorf(format string, a ...interface{}) error { - err, wrap := lastError(format, a) format = formatPlusW(format) - if err == nil { - return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)} + // Support a ": %[wsv]" suffix, which works well with xerrors.Formatter. + wrap := strings.HasSuffix(format, ": %w") + idx, format2, ok := parsePercentW(format) + percentWElsewhere := !wrap && idx >= 0 + if !percentWElsewhere && (wrap || strings.HasSuffix(format, ": %s") || strings.HasSuffix(format, ": %v")) { + err := errorAt(a, len(a)-1) + if err == nil { + return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)} + } + // TODO: this is not entirely correct. The error value could be + // printed elsewhere in format if it mixes numbered with unnumbered + // substitutions. With relatively small changes to doPrintf we can + // have it optionally ignore extra arguments and pass the argument + // list in its entirety. + msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...) + frame := Frame{} + if internal.EnableTrace { + frame = Caller(1) + } + if wrap { + return &wrapError{msg, err, frame} + } + return &noWrapError{msg, err, frame} + } + // Support %w anywhere. + // TODO: don't repeat the wrapped error's message when %w occurs in the middle. + msg := fmt.Sprintf(format2, a...) + if idx < 0 { + return &noWrapError{msg, nil, Caller(1)} + } + err := errorAt(a, idx) + if !ok || err == nil { + // Too many %ws or argument of %w is not an error. Approximate the Go + // 1.13 fmt.Errorf message. + return &noWrapError{fmt.Sprintf("%sw(%s)", percentBangString, msg), nil, Caller(1)} } - - // TODO: this is not entirely correct. The error value could be - // printed elsewhere in format if it mixes numbered with unnumbered - // substitutions. With relatively small changes to doPrintf we can - // have it optionally ignore extra arguments and pass the argument - // list in its entirety. - msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...) frame := Frame{} if internal.EnableTrace { frame = Caller(1) } - if wrap { - return &wrapError{msg, err, frame} + return &wrapError{msg, err, frame} +} + +func errorAt(args []interface{}, i int) error { + if i < 0 || i >= len(args) { + return nil + } + err, ok := args[i].(error) + if !ok { + return nil } - return &noWrapError{msg, err, frame} + return err } // formatPlusW is used to avoid the vet check that will barf at %w. @@ -48,24 +97,56 @@ func formatPlusW(s string) string { return s } -func lastError(format string, a []interface{}) (err error, wrap bool) { - wrap = strings.HasSuffix(format, ": %w") - if !wrap && - !strings.HasSuffix(format, ": %s") && - !strings.HasSuffix(format, ": %v") { - return nil, false - } - - if len(a) == 0 { - return nil, false +// Return the index of the only %w in format, or -1 if none. +// Also return a rewritten format string with %w replaced by %v, and +// false if there is more than one %w. +// TODO: handle "%[N]w". +func parsePercentW(format string) (idx int, newFormat string, ok bool) { + // Loosely copied from golang.org/x/tools/go/analysis/passes/printf/printf.go. + idx = -1 + ok = true + n := 0 + sz := 0 + var isW bool + for i := 0; i < len(format); i += sz { + if format[i] != '%' { + sz = 1 + continue + } + // "%%" is not a format directive. + if i+1 < len(format) && format[i+1] == '%' { + sz = 2 + continue + } + sz, isW = parsePrintfVerb(format[i:]) + if isW { + if idx >= 0 { + ok = false + } else { + idx = n + } + // "Replace" the last character, the 'w', with a 'v'. + p := i + sz - 1 + format = format[:p] + "v" + format[p+1:] + } + n++ } + return idx, format, ok +} - err, ok := a[len(a)-1].(error) - if !ok { - return nil, false +// Parse the printf verb starting with a % at s[0]. +// Return how many bytes it occupies and whether the verb is 'w'. +func parsePrintfVerb(s string) (int, bool) { + // Assume only that the directive is a sequence of non-letters followed by a single letter. + sz := 0 + var r rune + for i := 1; i < len(s); i += sz { + r, sz = utf8.DecodeRuneInString(s[i:]) + if unicode.IsLetter(r) { + return i + sz, r == 'w' + } } - - return err, wrap + return len(s), false } type noWrapError struct { diff --git a/vendor/golang.org/x/xerrors/wrap.go b/vendor/golang.org/x/xerrors/wrap.go index 9a3b510..9842758 100644 --- a/vendor/golang.org/x/xerrors/wrap.go +++ b/vendor/golang.org/x/xerrors/wrap.go @@ -35,6 +35,8 @@ func (e noWrapper) FormatError(p Printer) (next error) { // Unwrap returns the result of calling the Unwrap method on err, if err implements // Unwrap. Otherwise, Unwrap returns nil. +// +// Deprecated: As of Go 1.13, use errors.Unwrap instead. func Unwrap(err error) error { u, ok := err.(Wrapper) if !ok { @@ -47,6 +49,8 @@ func Unwrap(err error) error { // // An error is considered to match a target if it is equal to that target or if // it implements a method Is(error) bool such that Is(target) returns true. +// +// Deprecated: As of Go 1.13, use errors.Is instead. func Is(err, target error) bool { if target == nil { return err == target @@ -77,6 +81,8 @@ func Is(err, target error) bool { // // The As method should set the target to its value and return true if err // matches the type to which target points. +// +// Deprecated: As of Go 1.13, use errors.As instead. func As(err error, target interface{}) bool { if target == nil { panic("errors: target cannot be nil") diff --git a/vendor/modules.txt b/vendor/modules.txt index 14a095d..762c16b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,11 +1,11 @@ -# github.com/mediocregopher/radix/v3 v3.8.0 +# github.com/mediocregopher/radix/v3 v3.8.1 ## explicit; go 1.13 github.com/mediocregopher/radix/v3 github.com/mediocregopher/radix/v3/internal/bytesutil github.com/mediocregopher/radix/v3/resp github.com/mediocregopher/radix/v3/resp/resp2 github.com/mediocregopher/radix/v3/trace -# golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 -## explicit; go 1.11 +# golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 +## explicit; go 1.18 golang.org/x/xerrors golang.org/x/xerrors/internal