From 7f7329b245498f2e71318eac8763304580e17f63 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 12:01:20 +0000 Subject: [PATCH] Bump github.com/redis/go-redis/v9 from 9.12.1 to 9.14.0 Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.12.1 to 9.14.0. - [Release notes](https://github.com/redis/go-redis/releases) - [Changelog](https://github.com/redis/go-redis/blob/master/RELEASE-NOTES.md) - [Commits](https://github.com/redis/go-redis/compare/v9.12.1...v9.14.0) --- updated-dependencies: - dependency-name: github.com/redis/go-redis/v9 dependency-version: 9.14.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 +- .../redis/go-redis/v9/CONTRIBUTING.md | 2 +- vendor/github.com/redis/go-redis/v9/Makefile | 20 ++++ vendor/github.com/redis/go-redis/v9/README.md | 35 +----- .../redis/go-redis/v9/RELEASE-NOTES.md | 70 ++++++++++++ .../github.com/redis/go-redis/v9/commands.go | 1 + .../redis/go-redis/v9/docker-compose.yml | 10 +- .../redis/go-redis/v9/internal/pool/conn.go | 4 +- .../go-redis/v9/internal/proto/reader.go | 4 +- vendor/github.com/redis/go-redis/v9/json.go | 16 +++ .../github.com/redis/go-redis/v9/options.go | 9 +- .../redis/go-redis/v9/osscluster.go | 101 +++++++++++++----- .../github.com/redis/go-redis/v9/pipeline.go | 27 +++-- vendor/github.com/redis/go-redis/v9/redis.go | 10 +- vendor/github.com/redis/go-redis/v9/ring.go | 4 +- .../github.com/redis/go-redis/v9/sentinel.go | 26 +++-- .../github.com/redis/go-redis/v9/universal.go | 40 ++++++- .../github.com/redis/go-redis/v9/version.go | 2 +- vendor/modules.txt | 2 +- 20 files changed, 290 insertions(+), 99 deletions(-) diff --git a/go.mod b/go.mod index c515c06..5d9286e 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.24.0 require ( github.com/hashicorp/consul/api v1.32.1 github.com/hashicorp/go-hclog v1.6.3 - github.com/redis/go-redis/v9 v9.12.1 + github.com/redis/go-redis/v9 v9.14.0 github.com/stretchr/testify v1.11.1 ) diff --git a/go.sum b/go.sum index 0e83b48..d97f073 100644 --- a/go.sum +++ b/go.sum @@ -160,8 +160,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/redis/go-redis/v9 v9.12.1 h1:k5iquqv27aBtnTm2tIkROUDp8JBXhXZIVu1InSgvovg= -github.com/redis/go-redis/v9 v9.12.1/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= +github.com/redis/go-redis/v9 v9.14.0 h1:u4tNCjXOyzfgeLN+vAZaW1xUooqWDqVEsZN0U01jfAE= +github.com/redis/go-redis/v9 v9.14.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= diff --git a/vendor/github.com/redis/go-redis/v9/CONTRIBUTING.md b/vendor/github.com/redis/go-redis/v9/CONTRIBUTING.md index 7228a4a..8c68c52 100644 --- a/vendor/github.com/redis/go-redis/v9/CONTRIBUTING.md +++ b/vendor/github.com/redis/go-redis/v9/CONTRIBUTING.md @@ -37,7 +37,7 @@ Here's how to get started with your code contribution: > Note: this clones and builds the docker containers specified in `docker-compose.yml`, to understand more about > the infrastructure that will be started you can check the `docker-compose.yml`. You also have the possiblity > to specify the redis image that will be pulled with the env variable `CLIENT_LIBS_TEST_IMAGE`. -> By default the docker image that will be pulled and started is `redislabs/client-libs-test:rs-7.4.0-v2`. +> By default the docker image that will be pulled and started is `redislabs/client-libs-test:8.2.1-pre`. > If you want to test with newer Redis version, using a newer version of `redislabs/client-libs-test` should work out of the box. 4. While developing, make sure the tests pass by running `make test` (if you have the docker containers running, `make test.ci` may be sufficient). diff --git a/vendor/github.com/redis/go-redis/v9/Makefile b/vendor/github.com/redis/go-redis/v9/Makefile index 655f16f..0252a7e 100644 --- a/vendor/github.com/redis/go-redis/v9/Makefile +++ b/vendor/github.com/redis/go-redis/v9/Makefile @@ -1,6 +1,14 @@ GO_MOD_DIRS := $(shell find . -type f -name 'go.mod' -exec dirname {} \; | sort) +REDIS_VERSION ?= 8.2 +RE_CLUSTER ?= false +RCE_DOCKER ?= true +CLIENT_LIBS_TEST_IMAGE ?= redislabs/client-libs-test:8.2.1-pre docker.start: + export RE_CLUSTER=$(RE_CLUSTER) && \ + export RCE_DOCKER=$(RCE_DOCKER) && \ + export REDIS_VERSION=$(REDIS_VERSION) && \ + export CLIENT_LIBS_TEST_IMAGE=$(CLIENT_LIBS_TEST_IMAGE) && \ docker compose --profile all up -d --quiet-pull docker.stop: @@ -27,6 +35,9 @@ test.ci: set -e; for dir in $(GO_MOD_DIRS); do \ echo "go test in $${dir}"; \ (cd "$${dir}" && \ + export RE_CLUSTER=$(RE_CLUSTER) && \ + export RCE_DOCKER=$(RCE_DOCKER) && \ + export REDIS_VERSION=$(REDIS_VERSION) && \ go mod tidy -compat=1.18 && \ go vet && \ go test -v -coverprofile=coverage.txt -covermode=atomic ./... -race -skip Example); \ @@ -38,6 +49,9 @@ test.ci.skip-vectorsets: set -e; for dir in $(GO_MOD_DIRS); do \ echo "go test in $${dir} (skipping vector sets)"; \ (cd "$${dir}" && \ + export RE_CLUSTER=$(RE_CLUSTER) && \ + export RCE_DOCKER=$(RCE_DOCKER) && \ + export REDIS_VERSION=$(REDIS_VERSION) && \ go mod tidy -compat=1.18 && \ go vet && \ go test -v -coverprofile=coverage.txt -covermode=atomic ./... -race \ @@ -47,11 +61,17 @@ test.ci.skip-vectorsets: go vet -vettool ./internal/customvet/customvet bench: + export RE_CLUSTER=$(RE_CLUSTER) && \ + export RCE_DOCKER=$(RCE_DOCKER) && \ + export REDIS_VERSION=$(REDIS_VERSION) && \ go test ./... -test.run=NONE -test.bench=. -test.benchmem -skip Example .PHONY: all test test.ci test.ci.skip-vectorsets bench fmt build: + export RE_CLUSTER=$(RE_CLUSTER) && \ + export RCE_DOCKER=$(RCE_DOCKER) && \ + export REDIS_VERSION=$(REDIS_VERSION) && \ go build . fmt: diff --git a/vendor/github.com/redis/go-redis/v9/README.md b/vendor/github.com/redis/go-redis/v9/README.md index f4e73da..0716403 100644 --- a/vendor/github.com/redis/go-redis/v9/README.md +++ b/vendor/github.com/redis/go-redis/v9/README.md @@ -301,7 +301,7 @@ func main() { ### Buffer Size Configuration -go-redis uses 0.5MiB read and write buffers by default for optimal performance. For high-throughput applications or large pipelines, you can customize buffer sizes: +go-redis uses 32KiB read and write buffers by default for optimal performance. For high-throughput applications or large pipelines, you can customize buffer sizes: ```go rdb := redis.NewClient(&redis.Options{ @@ -376,7 +376,7 @@ You can find further details in the [query dialect documentation](https://redis. #### Custom buffer sizes Prior to v9.12, the buffer size was the default go value of 4096 bytes. Starting from v9.12, -go-redis uses 256KiB read and write buffers by default for optimal performance. +go-redis uses 32KiB read and write buffers by default for optimal performance. For high-throughput applications or large pipelines, you can customize buffer sizes: ```go @@ -432,36 +432,9 @@ res, err := rdb.Do(ctx, "set", "key", "value").Result() ## Run the test -go-redis will start a redis-server and run the test cases. - -The paths of redis-server bin file and redis config file are defined in `main_test.go`: - -```go -var ( - redisServerBin, _ = filepath.Abs(filepath.Join("testdata", "redis", "src", "redis-server")) - redisServerConf, _ = filepath.Abs(filepath.Join("testdata", "redis", "redis.conf")) -) -``` - -For local testing, you can change the variables to refer to your local files, or create a soft link -to the corresponding folder for redis-server and copy the config file to `testdata/redis/`: - -```shell -ln -s /usr/bin/redis-server ./go-redis/testdata/redis/src -cp ./go-redis/testdata/redis.conf ./go-redis/testdata/redis/ -``` - -Lastly, run: - -```shell -go test -``` - -Another option is to run your specific tests with an already running redis. The example below, tests -against a redis running on port 9999.: - +Recommended to use Docker, just need to run: ```shell -REDIS_PORT=9999 go test +make test ``` ## See also diff --git a/vendor/github.com/redis/go-redis/v9/RELEASE-NOTES.md b/vendor/github.com/redis/go-redis/v9/RELEASE-NOTES.md index 2597161..7121bd7 100644 --- a/vendor/github.com/redis/go-redis/v9/RELEASE-NOTES.md +++ b/vendor/github.com/redis/go-redis/v9/RELEASE-NOTES.md @@ -1,5 +1,75 @@ # Release Notes +# 9.14.0 (2025-09-10) + +## Highlights +- Added batch process method to the pipeline ([#3510](https://github.com/redis/go-redis/pull/3510)) + +# Changes + +## 🚀 New Features + +- Added batch process method to the pipeline ([#3510](https://github.com/redis/go-redis/pull/3510)) + +## 🐛 Bug Fixes + +- fix: SetErr on Cmd if the command cannot be queued correctly in multi/exec ([#3509](https://github.com/redis/go-redis/pull/3509)) + +## 🧰 Maintenance + +- Updates release drafter config to exclude dependabot ([#3511](https://github.com/redis/go-redis/pull/3511)) +- chore(deps): bump actions/setup-go from 5 to 6 ([#3504](https://github.com/redis/go-redis/pull/3504)) + +## Contributors +We'd like to thank all the contributors who worked on this release! + +[@elena-kolevska](https://github.com/elena-kolevksa), [@htemelski-redis](https://github.com/htemelski-redis) and [@ndyakov](https://github.com/ndyakov) + + +# 9.13.0 (2025-09-03) + +## Highlights +- Pipeliner expose queued commands ([#3496](https://github.com/redis/go-redis/pull/3496)) +- Ensure that JSON.GET returns Nil response ([#3470](https://github.com/redis/go-redis/pull/3470)) +- Fixes on Read and Write buffer sizes and UniversalOptions + +## Changes +- Pipeliner expose queued commands ([#3496](https://github.com/redis/go-redis/pull/3496)) +- fix(test): fix a timing issue in pubsub test ([#3498](https://github.com/redis/go-redis/pull/3498)) +- Allow users to enable read-write splitting in failover mode. ([#3482](https://github.com/redis/go-redis/pull/3482)) +- Set the read/write buffer size of the sentinel client to 4KiB ([#3476](https://github.com/redis/go-redis/pull/3476)) + +## 🚀 New Features + +- fix(otel): register wait metrics ([#3499](https://github.com/redis/go-redis/pull/3499)) +- Support subscriptions against cluster slave nodes ([#3480](https://github.com/redis/go-redis/pull/3480)) +- Add wait metrics to otel ([#3493](https://github.com/redis/go-redis/pull/3493)) +- Clean failing timeout implementation ([#3472](https://github.com/redis/go-redis/pull/3472)) + +## 🐛 Bug Fixes + +- Do not assume that all non-IP hosts are loopbacks ([#3085](https://github.com/redis/go-redis/pull/3085)) +- Ensure that JSON.GET returns Nil response ([#3470](https://github.com/redis/go-redis/pull/3470)) + +## 🧰 Maintenance + +- fix(otel): register wait metrics ([#3499](https://github.com/redis/go-redis/pull/3499)) +- fix(make test): Add default env in makefile ([#3491](https://github.com/redis/go-redis/pull/3491)) +- Update the introduction to running tests in README.md ([#3495](https://github.com/redis/go-redis/pull/3495)) +- test: Add comprehensive edge case tests for IncrByFloat command ([#3477](https://github.com/redis/go-redis/pull/3477)) +- Set the default read/write buffer size of Redis connection to 32KiB ([#3483](https://github.com/redis/go-redis/pull/3483)) +- Bumps test image to 8.2.1-pre ([#3478](https://github.com/redis/go-redis/pull/3478)) +- fix UniversalOptions miss ReadBufferSize and WriteBufferSize options ([#3485](https://github.com/redis/go-redis/pull/3485)) +- chore(deps): bump actions/checkout from 4 to 5 ([#3484](https://github.com/redis/go-redis/pull/3484)) +- Removes dry run for stale issues policy ([#3471](https://github.com/redis/go-redis/pull/3471)) +- Update otel metrics URL ([#3474](https://github.com/redis/go-redis/pull/3474)) + +## Contributors +We'd like to thank all the contributors who worked on this release! + +[@LINKIWI](https://github.com/LINKIWI), [@cxljs](https://github.com/cxljs), [@cybersmeashish](https://github.com/cybersmeashish), [@elena-kolevska](https://github.com/elena-kolevska), [@htemelski-redis](https://github.com/htemelski-redis), [@mwhooker](https://github.com/mwhooker), [@ndyakov](https://github.com/ndyakov), [@ofekshenawa](https://github.com/ofekshenawa), [@suever](https://github.com/suever) + + # 9.12.1 (2025-08-11) ## 🚀 Highlights In the last version (9.12.0) the client introduced bigger write and read buffer sized. The default value we set was 512KiB. diff --git a/vendor/github.com/redis/go-redis/v9/commands.go b/vendor/github.com/redis/go-redis/v9/commands.go index c035800..e9fd0f2 100644 --- a/vendor/github.com/redis/go-redis/v9/commands.go +++ b/vendor/github.com/redis/go-redis/v9/commands.go @@ -253,6 +253,7 @@ var ( _ Cmdable = (*Tx)(nil) _ Cmdable = (*Ring)(nil) _ Cmdable = (*ClusterClient)(nil) + _ Cmdable = (*Pipeline)(nil) ) type cmdable func(ctx context.Context, cmd Cmder) error diff --git a/vendor/github.com/redis/go-redis/v9/docker-compose.yml b/vendor/github.com/redis/go-redis/v9/docker-compose.yml index 3d4347b..cc864d8 100644 --- a/vendor/github.com/redis/go-redis/v9/docker-compose.yml +++ b/vendor/github.com/redis/go-redis/v9/docker-compose.yml @@ -2,7 +2,7 @@ services: redis: - image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2} + image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:8.2.1-pre} platform: linux/amd64 container_name: redis-standalone environment: @@ -23,7 +23,7 @@ services: - all osscluster: - image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2} + image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:8.2.1-pre} platform: linux/amd64 container_name: redis-osscluster environment: @@ -40,7 +40,7 @@ services: - all sentinel-cluster: - image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2} + image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:8.2.1-pre} platform: linux/amd64 container_name: redis-sentinel-cluster network_mode: "host" @@ -60,7 +60,7 @@ services: - all sentinel: - image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2} + image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:8.2.1-pre} platform: linux/amd64 container_name: redis-sentinel depends_on: @@ -84,7 +84,7 @@ services: - all ring-cluster: - image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:rs-7.4.0-v2} + image: ${CLIENT_LIBS_TEST_IMAGE:-redislabs/client-libs-test:8.2.1-pre} platform: linux/amd64 container_name: redis-ring-cluster environment: diff --git a/vendor/github.com/redis/go-redis/v9/internal/pool/conn.go b/vendor/github.com/redis/go-redis/v9/internal/pool/conn.go index 989ab10..6b02ddb 100644 --- a/vendor/github.com/redis/go-redis/v9/internal/pool/conn.go +++ b/vendor/github.com/redis/go-redis/v9/internal/pool/conn.go @@ -37,11 +37,11 @@ func NewConnWithBufferSize(netConn net.Conn, readBufSize, writeBufSize int) *Con createdAt: time.Now(), } - // Use specified buffer sizes, or fall back to 0.5MiB defaults if 0 + // Use specified buffer sizes, or fall back to 32KiB defaults if 0 if readBufSize > 0 { cn.rd = proto.NewReaderSize(netConn, readBufSize) } else { - cn.rd = proto.NewReader(netConn) // Uses 0.5MiB default + cn.rd = proto.NewReader(netConn) // Uses 32KiB default } if writeBufSize > 0 { diff --git a/vendor/github.com/redis/go-redis/v9/internal/proto/reader.go b/vendor/github.com/redis/go-redis/v9/internal/proto/reader.go index 13ff254..654f2ca 100644 --- a/vendor/github.com/redis/go-redis/v9/internal/proto/reader.go +++ b/vendor/github.com/redis/go-redis/v9/internal/proto/reader.go @@ -12,8 +12,8 @@ import ( "github.com/redis/go-redis/v9/internal/util" ) -// DefaultBufferSize is the default size for read/write buffers (256 KiB). -const DefaultBufferSize = 256 * 1024 +// DefaultBufferSize is the default size for read/write buffers (32 KiB). +const DefaultBufferSize = 32 * 1024 // redis resp protocol data type. const ( diff --git a/vendor/github.com/redis/go-redis/v9/json.go b/vendor/github.com/redis/go-redis/v9/json.go index b3cadf4..2b9fa52 100644 --- a/vendor/github.com/redis/go-redis/v9/json.go +++ b/vendor/github.com/redis/go-redis/v9/json.go @@ -82,6 +82,7 @@ func (cmd *JSONCmd) SetVal(val string) { cmd.val = val } +// Val returns the result of the JSON.GET command as a string. func (cmd *JSONCmd) Val() string { if len(cmd.val) == 0 && cmd.expanded != nil { val, err := json.Marshal(cmd.expanded) @@ -100,6 +101,7 @@ func (cmd *JSONCmd) Result() (string, error) { return cmd.Val(), cmd.Err() } +// Expanded returns the result of the JSON.GET command as unmarshalled JSON. func (cmd *JSONCmd) Expanded() (interface{}, error) { if len(cmd.val) != 0 && cmd.expanded == nil { err := json.Unmarshal([]byte(cmd.val), &cmd.expanded) @@ -113,11 +115,17 @@ func (cmd *JSONCmd) Expanded() (interface{}, error) { func (cmd *JSONCmd) readReply(rd *proto.Reader) error { // nil response from JSON.(M)GET (cmd.baseCmd.err will be "redis: nil") + // This happens when the key doesn't exist if cmd.baseCmd.Err() == Nil { cmd.val = "" return Nil } + // Handle other base command errors + if cmd.baseCmd.Err() != nil { + return cmd.baseCmd.Err() + } + if readType, err := rd.PeekReplyType(); err != nil { return err } else if readType == proto.RespArray { @@ -127,6 +135,13 @@ func (cmd *JSONCmd) readReply(rd *proto.Reader) error { return err } + // Empty array means no results found for JSON path, but key exists + // This should return "[]", not an error + if size == 0 { + cmd.val = "[]" + return nil + } + expanded := make([]interface{}, size) for i := 0; i < size; i++ { @@ -141,6 +156,7 @@ func (cmd *JSONCmd) readReply(rd *proto.Reader) error { return err } else if str == "" || err == Nil { cmd.val = "" + return Nil } else { cmd.val = str } diff --git a/vendor/github.com/redis/go-redis/v9/options.go b/vendor/github.com/redis/go-redis/v9/options.go index 6887b60..799cb53 100644 --- a/vendor/github.com/redis/go-redis/v9/options.go +++ b/vendor/github.com/redis/go-redis/v9/options.go @@ -135,14 +135,14 @@ type Options struct { // Larger buffers can improve performance for commands that return large responses. // Smaller buffers can improve memory usage for larger pools. // - // default: 256KiB (262144 bytes) + // default: 32KiB (32768 bytes) ReadBufferSize int // WriteBufferSize is the size of the bufio.Writer buffer for each connection. // Larger buffers can improve performance for large pipelines and commands with many arguments. // Smaller buffers can improve memory usage for larger pools. // - // default: 256KiB (262144 bytes) + // default: 32KiB (32768 bytes) WriteBufferSize int // PoolFIFO type of connection pool. @@ -231,6 +231,11 @@ type Options struct { // UnstableResp3 enables Unstable mode for Redis Search module with RESP3. // When unstable mode is enabled, the client will use RESP3 protocol and only be able to use RawResult UnstableResp3 bool + + // FailingTimeoutSeconds is the timeout in seconds for marking a cluster node as failing. + // When a node is marked as failing, it will be avoided for this duration. + // Default is 15 seconds. + FailingTimeoutSeconds int } func (opt *Options) init() { diff --git a/vendor/github.com/redis/go-redis/v9/osscluster.go b/vendor/github.com/redis/go-redis/v9/osscluster.go index 0f678e6..7c5a1a9 100644 --- a/vendor/github.com/redis/go-redis/v9/osscluster.go +++ b/vendor/github.com/redis/go-redis/v9/osscluster.go @@ -96,14 +96,14 @@ type ClusterOptions struct { // Larger buffers can improve performance for commands that return large responses. // Smaller buffers can improve memory usage for larger pools. // - // default: 256KiB (262144 bytes) + // default: 32KiB (32768 bytes) ReadBufferSize int // WriteBufferSize is the size of the bufio.Writer buffer for each connection. // Larger buffers can improve performance for large pipelines and commands with many arguments. // Smaller buffers can improve memory usage for larger pools. // - // default: 256KiB (262144 bytes) + // default: 32KiB (32768 bytes) WriteBufferSize int TLSConfig *tls.Config @@ -124,6 +124,11 @@ type ClusterOptions struct { // UnstableResp3 enables Unstable mode for Redis Search module with RESP3. UnstableResp3 bool + + // FailingTimeoutSeconds is the timeout in seconds for marking a cluster node as failing. + // When a node is marked as failing, it will be avoided for this duration. + // Default is 15 seconds. + FailingTimeoutSeconds int } func (opt *ClusterOptions) init() { @@ -180,6 +185,10 @@ func (opt *ClusterOptions) init() { if opt.NewClient == nil { opt.NewClient = NewClient } + + if opt.FailingTimeoutSeconds == 0 { + opt.FailingTimeoutSeconds = 15 + } } // ParseClusterURL parses a URL into ClusterOptions that can be used to connect to Redis. @@ -284,6 +293,7 @@ func setupClusterQueryParams(u *url.URL, o *ClusterOptions) (*ClusterOptions, er o.PoolTimeout = q.duration("pool_timeout") o.ConnMaxLifetime = q.duration("conn_max_lifetime") o.ConnMaxIdleTime = q.duration("conn_max_idle_time") + o.FailingTimeoutSeconds = q.int("failing_timeout_seconds") if q.err != nil { return nil, q.err @@ -330,20 +340,21 @@ func (opt *ClusterOptions) clientOptions() *Options { WriteTimeout: opt.WriteTimeout, ContextTimeoutEnabled: opt.ContextTimeoutEnabled, - PoolFIFO: opt.PoolFIFO, - PoolSize: opt.PoolSize, - PoolTimeout: opt.PoolTimeout, - MinIdleConns: opt.MinIdleConns, - MaxIdleConns: opt.MaxIdleConns, - MaxActiveConns: opt.MaxActiveConns, - ConnMaxIdleTime: opt.ConnMaxIdleTime, - ConnMaxLifetime: opt.ConnMaxLifetime, - ReadBufferSize: opt.ReadBufferSize, - WriteBufferSize: opt.WriteBufferSize, - DisableIdentity: opt.DisableIdentity, - DisableIndentity: opt.DisableIdentity, - IdentitySuffix: opt.IdentitySuffix, - TLSConfig: opt.TLSConfig, + PoolFIFO: opt.PoolFIFO, + PoolSize: opt.PoolSize, + PoolTimeout: opt.PoolTimeout, + MinIdleConns: opt.MinIdleConns, + MaxIdleConns: opt.MaxIdleConns, + MaxActiveConns: opt.MaxActiveConns, + ConnMaxIdleTime: opt.ConnMaxIdleTime, + ConnMaxLifetime: opt.ConnMaxLifetime, + ReadBufferSize: opt.ReadBufferSize, + WriteBufferSize: opt.WriteBufferSize, + DisableIdentity: opt.DisableIdentity, + DisableIndentity: opt.DisableIdentity, + IdentitySuffix: opt.IdentitySuffix, + FailingTimeoutSeconds: opt.FailingTimeoutSeconds, + TLSConfig: opt.TLSConfig, // If ClusterSlots is populated, then we probably have an artificial // cluster whose nodes are not in clustering mode (otherwise there isn't // much use for ClusterSlots config). This means we cannot execute the @@ -432,7 +443,7 @@ func (n *clusterNode) MarkAsFailing() { } func (n *clusterNode) Failing() bool { - const timeout = 15 // 15 seconds + timeout := int64(n.Client.opt.FailingTimeoutSeconds) failing := atomic.LoadUint32(&n.failing) if failing == 0 { @@ -770,12 +781,25 @@ func replaceLoopbackHost(nodeAddr, originHost string) string { return net.JoinHostPort(originHost, nodePort) } +// isLoopback returns true if the host is a loopback address. +// For IP addresses, it uses net.IP.IsLoopback(). +// For hostnames, it recognizes well-known loopback hostnames like "localhost" +// and Docker-specific loopback patterns like "*.docker.internal". func isLoopback(host string) bool { ip := net.ParseIP(host) - if ip == nil { + if ip != nil { + return ip.IsLoopback() + } + + if strings.ToLower(host) == "localhost" { + return true + } + + if strings.HasSuffix(strings.ToLower(host), ".docker.internal") { return true } - return ip.IsLoopback() + + return false } func (c *clusterState) slotMasterNode(slot int) (*clusterNode, error) { @@ -1688,10 +1712,16 @@ func (c *ClusterClient) txPipelineReadQueued( for _, cmd := range cmds { err := statusCmd.readReply(rd) - if err == nil || c.checkMovedErr(ctx, cmd, err, failedCmds) || isRedisError(err) { - continue + if err != nil { + if c.checkMovedErr(ctx, cmd, err, failedCmds) { + // will be processed later + continue + } + cmd.SetErr(err) + if !isRedisError(err) { + return err + } } - return err } // Parse number of replies. @@ -1810,14 +1840,33 @@ func (c *ClusterClient) pubSub() *PubSub { } var err error + if len(channels) > 0 { slot := hashtag.Slot(channels[0]) - node, err = c.slotMasterNode(ctx, slot) + + // newConn in PubSub is only used for subscription connections, so it is safe to + // assume that a slave node can always be used when client options specify ReadOnly. + if c.opt.ReadOnly { + state, err := c.state.Get(ctx) + if err != nil { + return nil, err + } + + node, err = c.slotReadOnlyNode(state, slot) + if err != nil { + return nil, err + } + } else { + node, err = c.slotMasterNode(ctx, slot) + if err != nil { + return nil, err + } + } } else { node, err = c.nodes.Random() - } - if err != nil { - return nil, err + if err != nil { + return nil, err + } } cn, err := node.Client.newConn(context.TODO()) diff --git a/vendor/github.com/redis/go-redis/v9/pipeline.go b/vendor/github.com/redis/go-redis/v9/pipeline.go index 1c11420..567bf12 100644 --- a/vendor/github.com/redis/go-redis/v9/pipeline.go +++ b/vendor/github.com/redis/go-redis/v9/pipeline.go @@ -7,7 +7,7 @@ import ( type pipelineExecer func(context.Context, []Cmder) error -// Pipeliner is an mechanism to realise Redis Pipeline technique. +// Pipeliner is a mechanism to realise Redis Pipeline technique. // // Pipelining is a technique to extremely speed up processing by packing // operations to batches, send them at once to Redis and read a replies in a @@ -23,21 +23,27 @@ type pipelineExecer func(context.Context, []Cmder) error type Pipeliner interface { StatefulCmdable - // Len is to obtain the number of commands in the pipeline that have not yet been executed. + // Len obtains the number of commands in the pipeline that have not yet been executed. Len() int // Do is an API for executing any command. // If a certain Redis command is not yet supported, you can use Do to execute it. Do(ctx context.Context, args ...interface{}) *Cmd - // Process is to put the commands to be executed into the pipeline buffer. + // Process queues the cmd for later execution. Process(ctx context.Context, cmd Cmder) error - // Discard is to discard all commands in the cache that have not yet been executed. + // BatchProcess adds multiple commands to be executed into the pipeline buffer. + BatchProcess(ctx context.Context, cmd ...Cmder) error + + // Discard discards all commands in the pipeline buffer that have not yet been executed. Discard() - // Exec is to send all the commands buffered in the pipeline to the redis-server. + // Exec sends all the commands buffered in the pipeline to the redis server. Exec(ctx context.Context) ([]Cmder, error) + + // Cmds returns the list of queued commands. + Cmds() []Cmder } var _ Pipeliner = (*Pipeline)(nil) @@ -76,7 +82,12 @@ func (c *Pipeline) Do(ctx context.Context, args ...interface{}) *Cmd { // Process queues the cmd for later execution. func (c *Pipeline) Process(ctx context.Context, cmd Cmder) error { - c.cmds = append(c.cmds, cmd) + return c.BatchProcess(ctx, cmd) +} + +// BatchProcess queues multiple cmds for later execution. +func (c *Pipeline) BatchProcess(ctx context.Context, cmd ...Cmder) error { + c.cmds = append(c.cmds, cmd...) return nil } @@ -119,3 +130,7 @@ func (c *Pipeline) TxPipelined(ctx context.Context, fn func(Pipeliner) error) ([ func (c *Pipeline) TxPipeline() Pipeliner { return c } + +func (c *Pipeline) Cmds() []Cmder { + return c.cmds +} diff --git a/vendor/github.com/redis/go-redis/v9/redis.go b/vendor/github.com/redis/go-redis/v9/redis.go index 43ab401..16e2130 100644 --- a/vendor/github.com/redis/go-redis/v9/redis.go +++ b/vendor/github.com/redis/go-redis/v9/redis.go @@ -630,6 +630,7 @@ func (c *baseClient) generalProcessPipeline( return err }) if lastErr == nil || !canRetry || !shouldRetry(lastErr, true) { + setCmdsErr(cmds, lastErr) return lastErr } } @@ -703,9 +704,12 @@ func txPipelineReadQueued(rd *proto.Reader, statusCmd *StatusCmd, cmds []Cmder) } // Parse +QUEUED. - for range cmds { - if err := statusCmd.readReply(rd); err != nil && !isRedisError(err) { - return err + for _, cmd := range cmds { + if err := statusCmd.readReply(rd); err != nil { + cmd.SetErr(err) + if !isRedisError(err) { + return err + } } } diff --git a/vendor/github.com/redis/go-redis/v9/ring.go b/vendor/github.com/redis/go-redis/v9/ring.go index 6c74031..3381460 100644 --- a/vendor/github.com/redis/go-redis/v9/ring.go +++ b/vendor/github.com/redis/go-redis/v9/ring.go @@ -128,14 +128,14 @@ type RingOptions struct { // Larger buffers can improve performance for commands that return large responses. // Smaller buffers can improve memory usage for larger pools. // - // default: 256KiB (262144 bytes) + // default: 32KiB (32768 bytes) ReadBufferSize int // WriteBufferSize is the size of the bufio.Writer buffer for each connection. // Larger buffers can improve performance for large pipelines and commands with many arguments. // Smaller buffers can improve memory usage for larger pools. // - // default: 256KiB (262144 bytes) + // default: 32KiB (32768 bytes) WriteBufferSize int TLSConfig *tls.Config diff --git a/vendor/github.com/redis/go-redis/v9/sentinel.go b/vendor/github.com/redis/go-redis/v9/sentinel.go index a858b08..e4c9d83 100644 --- a/vendor/github.com/redis/go-redis/v9/sentinel.go +++ b/vendor/github.com/redis/go-redis/v9/sentinel.go @@ -94,14 +94,14 @@ type FailoverOptions struct { // Larger buffers can improve performance for commands that return large responses. // Smaller buffers can improve memory usage for larger pools. // - // default: 256KiB (262144 bytes) + // default: 32KiB (32768 bytes) ReadBufferSize int // WriteBufferSize is the size of the bufio.Writer buffer for each connection. // Larger buffers can improve performance for large pipelines and commands with many arguments. // Smaller buffers can improve memory usage for larger pools. // - // default: 256KiB (262144 bytes) + // default: 32KiB (32768 bytes) WriteBufferSize int PoolFIFO bool @@ -129,7 +129,13 @@ type FailoverOptions struct { DisableIdentity bool IdentitySuffix string - UnstableResp3 bool + + // FailingTimeoutSeconds is the timeout in seconds for marking a cluster node as failing. + // When a node is marked as failing, it will be avoided for this duration. + // Only applies to failover cluster clients. Default is 15 seconds. + FailingTimeoutSeconds int + + UnstableResp3 bool } func (opt *FailoverOptions) clientOptions() *Options { @@ -195,8 +201,9 @@ func (opt *FailoverOptions) sentinelOptions(addr string) *Options { MinRetryBackoff: opt.MinRetryBackoff, MaxRetryBackoff: opt.MaxRetryBackoff, - ReadBufferSize: opt.ReadBufferSize, - WriteBufferSize: opt.WriteBufferSize, + // The sentinel client uses a 4KiB read/write buffer size. + ReadBufferSize: 4096, + WriteBufferSize: 4096, DialTimeout: opt.DialTimeout, ReadTimeout: opt.ReadTimeout, @@ -238,6 +245,7 @@ func (opt *FailoverOptions) clusterOptions() *ClusterOptions { MaxRedirects: opt.MaxRetries, + ReadOnly: opt.ReplicaOnly, RouteByLatency: opt.RouteByLatency, RouteRandomly: opt.RouteRandomly, @@ -263,10 +271,10 @@ func (opt *FailoverOptions) clusterOptions() *ClusterOptions { TLSConfig: opt.TLSConfig, - DisableIdentity: opt.DisableIdentity, - DisableIndentity: opt.DisableIndentity, - - IdentitySuffix: opt.IdentitySuffix, + DisableIdentity: opt.DisableIdentity, + DisableIndentity: opt.DisableIndentity, + IdentitySuffix: opt.IdentitySuffix, + FailingTimeoutSeconds: opt.FailingTimeoutSeconds, } } diff --git a/vendor/github.com/redis/go-redis/v9/universal.go b/vendor/github.com/redis/go-redis/v9/universal.go index 9d51b92..02da3be 100644 --- a/vendor/github.com/redis/go-redis/v9/universal.go +++ b/vendor/github.com/redis/go-redis/v9/universal.go @@ -61,6 +61,20 @@ type UniversalOptions struct { WriteTimeout time.Duration ContextTimeoutEnabled bool + // ReadBufferSize is the size of the bufio.Reader buffer for each connection. + // Larger buffers can improve performance for commands that return large responses. + // Smaller buffers can improve memory usage for larger pools. + // + // default: 32KiB (32768 bytes) + ReadBufferSize int + + // WriteBufferSize is the size of the bufio.Writer buffer for each connection. + // Larger buffers can improve performance for large pipelines and commands with many arguments. + // Smaller buffers can improve memory usage for larger pools. + // + // default: 32KiB (32768 bytes) + WriteBufferSize int + // PoolFIFO uses FIFO mode for each node connection pool GET/PUT (default LIFO). PoolFIFO bool @@ -98,7 +112,13 @@ type UniversalOptions struct { DisableIdentity bool IdentitySuffix string - UnstableResp3 bool + + // FailingTimeoutSeconds is the timeout in seconds for marking a cluster node as failing. + // When a node is marked as failing, it will be avoided for this duration. + // Only applies to cluster clients. Default is 15 seconds. + FailingTimeoutSeconds int + + UnstableResp3 bool // IsClusterMode can be used when only one Addrs is provided (e.g. Elasticache supports setting up cluster mode with configuration endpoint). IsClusterMode bool @@ -137,6 +157,9 @@ func (o *UniversalOptions) Cluster() *ClusterOptions { WriteTimeout: o.WriteTimeout, ContextTimeoutEnabled: o.ContextTimeoutEnabled, + ReadBufferSize: o.ReadBufferSize, + WriteBufferSize: o.WriteBufferSize, + PoolFIFO: o.PoolFIFO, PoolSize: o.PoolSize, @@ -149,10 +172,11 @@ func (o *UniversalOptions) Cluster() *ClusterOptions { TLSConfig: o.TLSConfig, - DisableIdentity: o.DisableIdentity, - DisableIndentity: o.DisableIndentity, - IdentitySuffix: o.IdentitySuffix, - UnstableResp3: o.UnstableResp3, + DisableIdentity: o.DisableIdentity, + DisableIndentity: o.DisableIndentity, + IdentitySuffix: o.IdentitySuffix, + FailingTimeoutSeconds: o.FailingTimeoutSeconds, + UnstableResp3: o.UnstableResp3, } } @@ -193,6 +217,9 @@ func (o *UniversalOptions) Failover() *FailoverOptions { WriteTimeout: o.WriteTimeout, ContextTimeoutEnabled: o.ContextTimeoutEnabled, + ReadBufferSize: o.ReadBufferSize, + WriteBufferSize: o.WriteBufferSize, + PoolFIFO: o.PoolFIFO, PoolSize: o.PoolSize, PoolTimeout: o.PoolTimeout, @@ -243,6 +270,9 @@ func (o *UniversalOptions) Simple() *Options { WriteTimeout: o.WriteTimeout, ContextTimeoutEnabled: o.ContextTimeoutEnabled, + ReadBufferSize: o.ReadBufferSize, + WriteBufferSize: o.WriteBufferSize, + PoolFIFO: o.PoolFIFO, PoolSize: o.PoolSize, PoolTimeout: o.PoolTimeout, diff --git a/vendor/github.com/redis/go-redis/v9/version.go b/vendor/github.com/redis/go-redis/v9/version.go index 96fb146..eab1511 100644 --- a/vendor/github.com/redis/go-redis/v9/version.go +++ b/vendor/github.com/redis/go-redis/v9/version.go @@ -2,5 +2,5 @@ package redis // Version is the current release version. func Version() string { - return "9.12.1" + return "9.14.0" } diff --git a/vendor/modules.txt b/vendor/modules.txt index 29dd9c7..57a7e8f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -64,7 +64,7 @@ github.com/mitchellh/mapstructure # github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 ## explicit github.com/pmezard/go-difflib/difflib -# github.com/redis/go-redis/v9 v9.12.1 +# github.com/redis/go-redis/v9 v9.14.0 ## explicit; go 1.18 github.com/redis/go-redis/v9 github.com/redis/go-redis/v9/auth