From 7daa7f91fd1081743d3eb8dbe8ee0125b791c3f9 Mon Sep 17 00:00:00 2001 From: Stephanie Hingtgen Date: Fri, 15 Oct 2021 23:04:25 -0500 Subject: [PATCH 1/9] feat: add ParseClusterURLs to allow for parsing of redis cluster urls into cluster options --- cluster.go | 139 +++++++++++++++++++++++++++++++++ cluster_test.go | 198 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 337 insertions(+) diff --git a/cluster.go b/cluster.go index a54f2f37e..5ecde2e06 100644 --- a/cluster.go +++ b/cluster.go @@ -6,8 +6,10 @@ import ( "fmt" "math" "net" + "net/url" "runtime" "sort" + "strings" "sync" "sync/atomic" "time" @@ -131,6 +133,143 @@ func (opt *ClusterOptions) init() { } } +// ParseClusterURLs parses an array of URLs into ClusterOptions that can be used to connect to Redis. +// The strings in the array must be in the form: +// redis://:@: +// or +// rediss://:@: +// All strings in the array must use the same scheme, username, and password. +// +// Most Option fields can be set using query parameters, with the following restrictions: +// - field names are mapped using snake-case conversion: to set MaxRetries, use max_retries +// - only scalar type fields are supported (bool, int, time.Duration) +// - for time.Duration fields, values must be a valid input for time.ParseDuration(); +// additionally a plain integer as value (i.e. without unit) is intepreted as seconds +// - to disable a duration field, use value less than or equal to 0; to use the default +// value, leave the value blank or remove the parameter +// - only the last value is interpreted if a parameter is given multiple times +// - fields "network", "addr", "username" and "password" can only be set using other +// URL attributes (scheme, host, userinfo, resp.), query paremeters using these +// names will be treated as unknown parameters +// - unknown parameter names will result in an error +// - if query parameters differ between urls, the last one in the array will be used +// Examples: +// [ +// redis://user:password@localhost:6789?dial_timeout=3&read_timeout=6s&max_retries=2, +// redis://user:password@localhost:6790?dial_timeout=3&read_timeout=6s&max_retries=2, +// redis://user:password@localhost:6791?dial_timeout=3&read_timeout=6s&max_retries=5, +// ] +// is equivalent to: +// &ClusterOptions{ +// Addr: ["localhost:6789", "localhost:6790", "localhost:6791"] +// DialTimeout: 3 * time.Second, // no time unit = seconds +// ReadTimeout: 6 * time.Second, +// MaxRetries: 5, // last one in the array is used +// } +func ParseClusterURLs(redisURLs []string) (*ClusterOptions, error) { + o := &ClusterOptions{} + previousScheme := "" + + // loop through all the URLs and retrieve the addresses as well as the + // cluster options + for _, redisURL := range redisURLs { + u, err := url.Parse(redisURL) + if err != nil { + return nil, err + } + + h, p, err := net.SplitHostPort(u.Host) + if err != nil { + h = u.Host + } + if h == "" { + h = "localhost" + } + if p == "" { + p = "6379" + } + o.Addrs = append(o.Addrs, net.JoinHostPort(h, p)) + + // all URLS must use the same scheme + if previousScheme != "" && u.Scheme != previousScheme { + return nil, fmt.Errorf("redis: mismatch schemes: %s and %s", previousScheme, u.Scheme) + } + previousScheme = u.Scheme + + // setup username, password, and other configurations + o, err = setupClusterConn(u, h, o) + if err != nil { + return nil, err + } + } + return o, nil +} + +// setupClusterConn gets the username and password from the URL and the query parameters. +func setupClusterConn(u *url.URL, host string, o *ClusterOptions) (*ClusterOptions, error) { + // retrieve the configuration from the query parameters + o, err := setupClusterQueryParams(u, o) + if err != nil { + return nil, err + } + + switch u.Scheme { + case "rediss": + o.TLSConfig = &tls.Config{ServerName: host} + fallthrough + case "redis": + // get the username & password - they must be consistent across urls + u, p := getUserPassword(u) + + if o.Username != "" && o.Username != u { + return nil, fmt.Errorf("redis: mismatch usernames: %s and %s", o.Username, u) + } + if o.Password != "" && o.Password != p { + return nil, fmt.Errorf("redis: mismatch passwords") + } + + o.Username, o.Password = u, p + + return o, nil + default: + return nil, fmt.Errorf("redis: invalid URL scheme: %s", u.Scheme) + } +} + +// setupClusterQueryParams converts query parameters in u to option value in o. +func setupClusterQueryParams(u *url.URL, o *ClusterOptions) (*ClusterOptions, error) { + q := queryOptions{q: u.Query()} + + o.MaxRedirects = q.int("max_redirects") + o.ReadOnly = q.bool("read_only") + o.RouteByLatency = q.bool("route_by_latency") + o.RouteByLatency = q.bool("route_randomly") + o.MaxRetries = q.int("max_retries") + o.MinRetryBackoff = q.duration("min_retry_backoff") + o.MaxRetryBackoff = q.duration("max_retry_backoff") + o.DialTimeout = q.duration("dial_timeout") + o.ReadTimeout = q.duration("read_timeout") + o.WriteTimeout = q.duration("write_timeout") + o.PoolFIFO = q.bool("pool_fifo") + o.PoolSize = q.int("pool_size") + o.MinIdleConns = q.int("min_idle_conns") + o.MaxConnAge = q.duration("max_conn_age") + o.PoolTimeout = q.duration("pool_timeout") + o.IdleTimeout = q.duration("idle_timeout") + o.IdleCheckFrequency = q.duration("idle_check_frequency") + + if q.err != nil { + return nil, q.err + } + + // any parameters left? + if r := q.remaining(); len(r) > 0 { + return nil, fmt.Errorf("redis: unexpected option: %s", strings.Join(r, ", ")) + } + + return o, nil +} + func (opt *ClusterOptions) clientOptions() *Options { const disableIdleCheck = -1 diff --git a/cluster_test.go b/cluster_test.go index 6ee7364e5..92ca085fd 100644 --- a/cluster_test.go +++ b/cluster_test.go @@ -2,11 +2,15 @@ package redis_test import ( "context" + "crypto/tls" + "errors" "fmt" "net" + "reflect" "strconv" "strings" "sync" + "testing" "time" . "github.com/onsi/ginkgo" @@ -1281,3 +1285,197 @@ var _ = Describe("ClusterClient timeout", func() { testTimeout() }) }) + +func TestParseClusterURLs(t *testing.T) { + cases := []struct { + test string + urls []string + o *redis.ClusterOptions // expected value + err error + }{ + { + test: "ParseRedisURL", + urls: []string{"redis://localhost:123"}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}}, + }, { + test: "ParseRedissURL", + urls: []string{"rediss://localhost:123"}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, TLSConfig: &tls.Config{ /* no deep comparison */ }}, + }, { + test: "MissingRedisPort", + urls: []string{"redis://localhost"}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:6379"}}, + }, { + test: "MissingRedissPort", + urls: []string{"rediss://localhost"}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:6379"}, TLSConfig: &tls.Config{ /* no deep comparison */ }}, + }, { + test: "MultipleRedisURLs", + urls: []string{"redis://localhost:123", "redis://localhost:1234"}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123", "localhost:1234"}}, + }, { + test: "MultipleRedissURLs", + urls: []string{"rediss://localhost:123", "rediss://localhost:1234"}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123", "localhost:1234"}, TLSConfig: &tls.Config{ /* no deep comparison */ }}, + }, { + test: "OnlyPassword", + urls: []string{"redis://:bar@localhost:123"}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, Password: "bar"}, + }, { + test: "OnlyUser", + urls: []string{"redis://foo@localhost:123"}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, Username: "foo"}, + }, { + test: "RedisUsernamePassword", + urls: []string{"redis://foo:bar@localhost:123"}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, Username: "foo", Password: "bar"}, + }, { + test: "RedissUsernamePassword", + urls: []string{"rediss://foo:bar@localhost:123", "rediss://foo:bar@localhost:1234"}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123", "localhost:1234"}, Username: "foo", Password: "bar", TLSConfig: &tls.Config{ /* no deep comparison */ }}, + }, { + test: "QueryParameters", + urls: []string{"redis://localhost:123?read_timeout=2&pool_fifo=true"}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, ReadTimeout: 2 * time.Second, PoolFIFO: true}, + }, { + test: "UseFinalQueryParameters", + urls: []string{"redis://localhost:123?read_timeout=2&pool_fifo=true", "redis://localhost:1234?read_timeout=3&pool_fifo=true"}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123", "localhost:1234"}, ReadTimeout: 3 * time.Second, PoolFIFO: true}, + }, { + test: "DisabledTimeout", + urls: []string{"redis://localhost:123?idle_timeout=0"}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, IdleTimeout: -1}, + }, { + test: "DisabledTimeoutNeg", + urls: []string{"redis://localhost:123?idle_timeout=-1"}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, IdleTimeout: -1}, + }, { + test: "UseDefault", + urls: []string{"redis://localhost:123?idle_timeout="}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, IdleTimeout: 0}, + }, { + test: "UseDefaultMissing=", + urls: []string{"redis://localhost:123?idle_timeout"}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, IdleTimeout: 0}, + }, { + test: "RedisPasswordMismatch", + urls: []string{"redis://foo:bar@localhost:123", "redis://foo:barr@localhost:1234"}, + err: errors.New(`redis: mismatch passwords`), + }, { + test: "RedisUsernameMismatch", + urls: []string{"redis://fooo:bar@localhost:123", "redis://foo:bar@localhost:1234"}, + err: errors.New(`redis: mismatch usernames: fooo and foo`), + }, { + test: "RedissPasswordMismatch", + urls: []string{"rediss://foo:bar@localhost:123", "rediss://foo:barr@localhost:1234"}, + err: errors.New(`redis: mismatch passwords`), + }, { + test: "RedissUsernameMismatch", + urls: []string{"rediss://foo:bar@localhost:123", "rediss://fooo:bar@localhost:1234"}, + err: errors.New(`redis: mismatch usernames: foo and fooo`), + }, { + test: "SchemeMismatch", + urls: []string{"rediss://foo:bar@localhost:123", "redis://foo:bar@localhost:1234"}, + err: errors.New(`redis: mismatch schemes: rediss and redis`), + }, { + test: "SchemeMismatch", + urls: []string{"redis://foo:bar@localhost:123", "localhost:1234"}, + err: errors.New(`redis: mismatch schemes: redis and localhost`), + }, { + test: "InvalidInt", + urls: []string{"redis://localhost?pool_size=five"}, + err: errors.New(`redis: invalid pool_size number: strconv.Atoi: parsing "five": invalid syntax`), + }, { + test: "InvalidBool", + urls: []string{"redis://localhost?pool_fifo=yes"}, + err: errors.New(`redis: invalid pool_fifo boolean: expected true/false/1/0 or an empty string, got "yes"`), + }, { + test: "UnknownParam", + urls: []string{"redis://localhost?abc=123"}, + err: errors.New("redis: unexpected option: abc"), + }, { + test: "InvalidScheme", + urls: []string{"https://google.com"}, + err: errors.New("redis: invalid URL scheme: https"), + }, + } + + for i := range cases { + tc := cases[i] + t.Run(tc.test, func(t *testing.T) { + t.Parallel() + + actual, err := redis.ParseClusterURLs(tc.urls) + if tc.err == nil && err != nil { + t.Fatalf("unexpected error: %q", err) + return + } + if tc.err != nil && err != nil { + if tc.err.Error() != err.Error() { + t.Fatalf("got %q, expected %q", err, tc.err) + } + return + } + comprareOptions(t, actual, tc.o) + }) + } +} + +func comprareOptions(t *testing.T, actual, expected *redis.ClusterOptions) { + t.Helper() + + if !reflect.DeepEqual(actual.Addrs, expected.Addrs) { + t.Errorf("got %q, want %q", actual.Addrs, expected.Addrs) + } + if actual.TLSConfig == nil && expected.TLSConfig != nil { + t.Errorf("got nil TLSConfig, expected a TLSConfig") + } + if actual.TLSConfig != nil && expected.TLSConfig == nil { + t.Errorf("got TLSConfig, expected no TLSConfig") + } + if actual.Username != expected.Username { + t.Errorf("Username: got %q, expected %q", actual.Username, expected.Username) + } + if actual.Password != expected.Password { + t.Errorf("Password: got %q, expected %q", actual.Password, expected.Password) + } + if actual.MaxRetries != expected.MaxRetries { + t.Errorf("MaxRetries: got %v, expected %v", actual.MaxRetries, expected.MaxRetries) + } + if actual.MinRetryBackoff != expected.MinRetryBackoff { + t.Errorf("MinRetryBackoff: got %v, expected %v", actual.MinRetryBackoff, expected.MinRetryBackoff) + } + if actual.MaxRetryBackoff != expected.MaxRetryBackoff { + t.Errorf("MaxRetryBackoff: got %v, expected %v", actual.MaxRetryBackoff, expected.MaxRetryBackoff) + } + if actual.DialTimeout != expected.DialTimeout { + t.Errorf("DialTimeout: got %v, expected %v", actual.DialTimeout, expected.DialTimeout) + } + if actual.ReadTimeout != expected.ReadTimeout { + t.Errorf("ReadTimeout: got %v, expected %v", actual.ReadTimeout, expected.ReadTimeout) + } + if actual.WriteTimeout != expected.WriteTimeout { + t.Errorf("WriteTimeout: got %v, expected %v", actual.WriteTimeout, expected.WriteTimeout) + } + if actual.PoolFIFO != expected.PoolFIFO { + t.Errorf("PoolFIFO: got %v, expected %v", actual.PoolFIFO, expected.PoolFIFO) + } + if actual.PoolSize != expected.PoolSize { + t.Errorf("PoolSize: got %v, expected %v", actual.PoolSize, expected.PoolSize) + } + if actual.MinIdleConns != expected.MinIdleConns { + t.Errorf("MinIdleConns: got %v, expected %v", actual.MinIdleConns, expected.MinIdleConns) + } + if actual.MaxConnAge != expected.MaxConnAge { + t.Errorf("MaxConnAge: got %v, expected %v", actual.MaxConnAge, expected.MaxConnAge) + } + if actual.PoolTimeout != expected.PoolTimeout { + t.Errorf("PoolTimeout: got %v, expected %v", actual.PoolTimeout, expected.PoolTimeout) + } + if actual.IdleTimeout != expected.IdleTimeout { + t.Errorf("IdleTimeout: got %v, expected %v", actual.IdleTimeout, expected.IdleTimeout) + } + if actual.IdleCheckFrequency != expected.IdleCheckFrequency { + t.Errorf("IdleCheckFrequency: got %v, expected %v", actual.IdleCheckFrequency, expected.IdleCheckFrequency) + } +} From 175d0d81fcef65aec8cee8e814b2e8e429971805 Mon Sep 17 00:00:00 2001 From: Stephanie Hingtgen Date: Mon, 18 Oct 2021 09:07:36 -0500 Subject: [PATCH 2/9] feat: update to ParseClusterURL and use addr param --- cluster.go | 117 +++++++++++++++++++++++------------------------- cluster_test.go | 84 +++++++++++++--------------------- options.go | 9 +++- 3 files changed, 97 insertions(+), 113 deletions(-) diff --git a/cluster.go b/cluster.go index 5ecde2e06..f7777e8a6 100644 --- a/cluster.go +++ b/cluster.go @@ -133,12 +133,15 @@ func (opt *ClusterOptions) init() { } } -// ParseClusterURLs parses an array of URLs into ClusterOptions that can be used to connect to Redis. -// The strings in the array must be in the form: +// ParseClusterURL parses a URL into ClusterOptions that can be used to connect to Redis. +// The URL must be in the form: // redis://:@: // or // rediss://:@: -// All strings in the array must use the same scheme, username, and password. +// To add additional addresses, specify the query parameter, "addr" one or more times. e.g: +// redis://:@:?addr=:&addr=: +// or +// rediss://:@:?addr=:&addr=: // // Most Option fields can be set using query parameters, with the following restrictions: // - field names are mapped using snake-case conversion: to set MaxRetries, use max_retries @@ -152,88 +155,66 @@ func (opt *ClusterOptions) init() { // URL attributes (scheme, host, userinfo, resp.), query paremeters using these // names will be treated as unknown parameters // - unknown parameter names will result in an error -// - if query parameters differ between urls, the last one in the array will be used -// Examples: -// [ -// redis://user:password@localhost:6789?dial_timeout=3&read_timeout=6s&max_retries=2, -// redis://user:password@localhost:6790?dial_timeout=3&read_timeout=6s&max_retries=2, -// redis://user:password@localhost:6791?dial_timeout=3&read_timeout=6s&max_retries=5, -// ] +// Example: +// redis://user:password@localhost:6789?dial_timeout=3&read_timeout=6s&max_retries=2&addr=localhost:6790&addr=localhost:6791 // is equivalent to: // &ClusterOptions{ // Addr: ["localhost:6789", "localhost:6790", "localhost:6791"] // DialTimeout: 3 * time.Second, // no time unit = seconds // ReadTimeout: 6 * time.Second, -// MaxRetries: 5, // last one in the array is used +// MaxRetries: 2, // } -func ParseClusterURLs(redisURLs []string) (*ClusterOptions, error) { +func ParseClusterURL(redisURL string) (*ClusterOptions, error) { o := &ClusterOptions{} - previousScheme := "" - // loop through all the URLs and retrieve the addresses as well as the - // cluster options - for _, redisURL := range redisURLs { - u, err := url.Parse(redisURL) - if err != nil { - return nil, err - } + u, err := url.Parse(redisURL) + if err != nil { + return nil, err + } - h, p, err := net.SplitHostPort(u.Host) - if err != nil { - h = u.Host - } - if h == "" { - h = "localhost" - } - if p == "" { - p = "6379" - } - o.Addrs = append(o.Addrs, net.JoinHostPort(h, p)) + // add base URL to the array of addresses + // more addresses may be added through the URL params + h, p, err := net.SplitHostPort(u.Host) + if err != nil { + h = u.Host + } + if h == "" { + h = "localhost" + } + if p == "" { + p = "6379" + } - // all URLS must use the same scheme - if previousScheme != "" && u.Scheme != previousScheme { - return nil, fmt.Errorf("redis: mismatch schemes: %s and %s", previousScheme, u.Scheme) - } - previousScheme = u.Scheme + o.Addrs = append(o.Addrs, net.JoinHostPort(h, p)) - // setup username, password, and other configurations - o, err = setupClusterConn(u, h, o) - if err != nil { - return nil, err - } + // setup username, password, and other configurations + o, err = setupClusterConn(u, h, o) + if err != nil { + return nil, err } + return o, nil } // setupClusterConn gets the username and password from the URL and the query parameters. func setupClusterConn(u *url.URL, host string, o *ClusterOptions) (*ClusterOptions, error) { - // retrieve the configuration from the query parameters - o, err := setupClusterQueryParams(u, o) - if err != nil { - return nil, err - } - switch u.Scheme { case "rediss": o.TLSConfig = &tls.Config{ServerName: host} fallthrough case "redis": - // get the username & password - they must be consistent across urls - u, p := getUserPassword(u) - - if o.Username != "" && o.Username != u { - return nil, fmt.Errorf("redis: mismatch usernames: %s and %s", o.Username, u) - } - if o.Password != "" && o.Password != p { - return nil, fmt.Errorf("redis: mismatch passwords") - } - - o.Username, o.Password = u, p - - return o, nil + o.Username, o.Password = getUserPassword(u) default: return nil, fmt.Errorf("redis: invalid URL scheme: %s", u.Scheme) } + + // retrieve the configuration from the query parameters + o, err := setupClusterQueryParams(u, o) + if err != nil { + return nil, err + } + + return o, nil } // setupClusterQueryParams converts query parameters in u to option value in o. @@ -262,6 +243,22 @@ func setupClusterQueryParams(u *url.URL, o *ClusterOptions) (*ClusterOptions, er return nil, q.err } + // addr can be specified as many times as needed + addr := q.string("addr") + for addr != "" { + h, p, err := net.SplitHostPort(addr) + if err != nil || h == "" || p == "" { + return nil, fmt.Errorf("redis: unable to parse addr param: %s", addr) + } + + o.Addrs = append(o.Addrs, net.JoinHostPort(h, p)) + + addr = q.string("addr") + if q.err != nil { + return nil, q.err + } + } + // any parameters left? if r := q.remaining(); len(r) > 0 { return nil, fmt.Errorf("redis: unexpected option: %s", strings.Join(r, ", ")) diff --git a/cluster_test.go b/cluster_test.go index 92ca085fd..f923112d7 100644 --- a/cluster_test.go +++ b/cluster_test.go @@ -1286,116 +1286,92 @@ var _ = Describe("ClusterClient timeout", func() { }) }) -func TestParseClusterURLs(t *testing.T) { +func TestParseClusterURL(t *testing.T) { cases := []struct { test string - urls []string + url string o *redis.ClusterOptions // expected value err error }{ { test: "ParseRedisURL", - urls: []string{"redis://localhost:123"}, + url: "redis://localhost:123", o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}}, }, { test: "ParseRedissURL", - urls: []string{"rediss://localhost:123"}, + url: "rediss://localhost:123", o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, TLSConfig: &tls.Config{ /* no deep comparison */ }}, }, { test: "MissingRedisPort", - urls: []string{"redis://localhost"}, + url: "redis://localhost", o: &redis.ClusterOptions{Addrs: []string{"localhost:6379"}}, }, { test: "MissingRedissPort", - urls: []string{"rediss://localhost"}, + url: "rediss://localhost", o: &redis.ClusterOptions{Addrs: []string{"localhost:6379"}, TLSConfig: &tls.Config{ /* no deep comparison */ }}, }, { test: "MultipleRedisURLs", - urls: []string{"redis://localhost:123", "redis://localhost:1234"}, - o: &redis.ClusterOptions{Addrs: []string{"localhost:123", "localhost:1234"}}, + url: "redis://localhost:123?addr=localhost:1234&addr=localhost:12345", + o: &redis.ClusterOptions{Addrs: []string{"localhost:123", "localhost:12345", "localhost:1234"}}, }, { test: "MultipleRedissURLs", - urls: []string{"rediss://localhost:123", "rediss://localhost:1234"}, - o: &redis.ClusterOptions{Addrs: []string{"localhost:123", "localhost:1234"}, TLSConfig: &tls.Config{ /* no deep comparison */ }}, + url: "rediss://localhost:123?addr=localhost:1234&addr=localhost:12345", + o: &redis.ClusterOptions{Addrs: []string{"localhost:123", "localhost:12345", "localhost:1234"}, TLSConfig: &tls.Config{ /* no deep comparison */ }}, }, { test: "OnlyPassword", - urls: []string{"redis://:bar@localhost:123"}, + url: "redis://:bar@localhost:123", o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, Password: "bar"}, }, { test: "OnlyUser", - urls: []string{"redis://foo@localhost:123"}, + url: "redis://foo@localhost:123", o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, Username: "foo"}, }, { test: "RedisUsernamePassword", - urls: []string{"redis://foo:bar@localhost:123"}, + url: "redis://foo:bar@localhost:123", o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, Username: "foo", Password: "bar"}, }, { test: "RedissUsernamePassword", - urls: []string{"rediss://foo:bar@localhost:123", "rediss://foo:bar@localhost:1234"}, + url: "rediss://foo:bar@localhost:123?addr=localhost:1234", o: &redis.ClusterOptions{Addrs: []string{"localhost:123", "localhost:1234"}, Username: "foo", Password: "bar", TLSConfig: &tls.Config{ /* no deep comparison */ }}, }, { test: "QueryParameters", - urls: []string{"redis://localhost:123?read_timeout=2&pool_fifo=true"}, - o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, ReadTimeout: 2 * time.Second, PoolFIFO: true}, - }, { - test: "UseFinalQueryParameters", - urls: []string{"redis://localhost:123?read_timeout=2&pool_fifo=true", "redis://localhost:1234?read_timeout=3&pool_fifo=true"}, - o: &redis.ClusterOptions{Addrs: []string{"localhost:123", "localhost:1234"}, ReadTimeout: 3 * time.Second, PoolFIFO: true}, + url: "redis://localhost:123?read_timeout=2&pool_fifo=true&addr=localhost:1234", + o: &redis.ClusterOptions{Addrs: []string{"localhost:123", "localhost:1234"}, ReadTimeout: 2 * time.Second, PoolFIFO: true}, }, { test: "DisabledTimeout", - urls: []string{"redis://localhost:123?idle_timeout=0"}, + url: "redis://localhost:123?idle_timeout=0", o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, IdleTimeout: -1}, }, { test: "DisabledTimeoutNeg", - urls: []string{"redis://localhost:123?idle_timeout=-1"}, + url: "redis://localhost:123?idle_timeout=-1", o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, IdleTimeout: -1}, }, { test: "UseDefault", - urls: []string{"redis://localhost:123?idle_timeout="}, + url: "redis://localhost:123?idle_timeout=", o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, IdleTimeout: 0}, }, { test: "UseDefaultMissing=", - urls: []string{"redis://localhost:123?idle_timeout"}, + url: "redis://localhost:123?idle_timeout", o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, IdleTimeout: 0}, }, { - test: "RedisPasswordMismatch", - urls: []string{"redis://foo:bar@localhost:123", "redis://foo:barr@localhost:1234"}, - err: errors.New(`redis: mismatch passwords`), - }, { - test: "RedisUsernameMismatch", - urls: []string{"redis://fooo:bar@localhost:123", "redis://foo:bar@localhost:1234"}, - err: errors.New(`redis: mismatch usernames: fooo and foo`), - }, { - test: "RedissPasswordMismatch", - urls: []string{"rediss://foo:bar@localhost:123", "rediss://foo:barr@localhost:1234"}, - err: errors.New(`redis: mismatch passwords`), - }, { - test: "RedissUsernameMismatch", - urls: []string{"rediss://foo:bar@localhost:123", "rediss://fooo:bar@localhost:1234"}, - err: errors.New(`redis: mismatch usernames: foo and fooo`), - }, { - test: "SchemeMismatch", - urls: []string{"rediss://foo:bar@localhost:123", "redis://foo:bar@localhost:1234"}, - err: errors.New(`redis: mismatch schemes: rediss and redis`), - }, { - test: "SchemeMismatch", - urls: []string{"redis://foo:bar@localhost:123", "localhost:1234"}, - err: errors.New(`redis: mismatch schemes: redis and localhost`), + test: "InvalidQueryAddr", + url: "rediss://foo:bar@localhost:123?addr=rediss://foo:barr@localhost:1234", + err: errors.New(`redis: unable to parse addr param: rediss://foo:barr@localhost:1234`), }, { test: "InvalidInt", - urls: []string{"redis://localhost?pool_size=five"}, + url: "redis://localhost?pool_size=five", err: errors.New(`redis: invalid pool_size number: strconv.Atoi: parsing "five": invalid syntax`), }, { test: "InvalidBool", - urls: []string{"redis://localhost?pool_fifo=yes"}, + url: "redis://localhost?pool_fifo=yes", err: errors.New(`redis: invalid pool_fifo boolean: expected true/false/1/0 or an empty string, got "yes"`), }, { test: "UnknownParam", - urls: []string{"redis://localhost?abc=123"}, + url: "redis://localhost?abc=123", err: errors.New("redis: unexpected option: abc"), }, { test: "InvalidScheme", - urls: []string{"https://google.com"}, + url: "https://google.com", err: errors.New("redis: invalid URL scheme: https"), }, } @@ -1405,11 +1381,15 @@ func TestParseClusterURLs(t *testing.T) { t.Run(tc.test, func(t *testing.T) { t.Parallel() - actual, err := redis.ParseClusterURLs(tc.urls) + actual, err := redis.ParseClusterURL(tc.url) if tc.err == nil && err != nil { t.Fatalf("unexpected error: %q", err) return } + if tc.err != nil && err == nil { + t.Fatalf("expected error: got %+v", actual) + return + } if tc.err != nil && err != nil { if tc.err.Error() != err.Error() { t.Fatalf("got %q, expected %q", err, tc.err) diff --git a/options.go b/options.go index a4abe32c3..ed20c5127 100644 --- a/options.go +++ b/options.go @@ -296,7 +296,14 @@ func (o *queryOptions) string(name string) string { if len(vs) == 0 { return "" } - delete(o.q, name) // enable detection of unknown parameters + + // enable detection of unknown parameters + if len(vs) > 1 { + o.q[name] = o.q[name][:len(vs)-1] + } else { + delete(o.q, name) + } + return vs[len(vs)-1] } From eb8d0fc81e7f9fbc8a5f214db1f07febca7cadb3 Mon Sep 17 00:00:00 2001 From: Stephanie Hingtgen Date: Mon, 18 Oct 2021 09:09:24 -0500 Subject: [PATCH 3/9] feat: fix linter --- cluster.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cluster.go b/cluster.go index f7777e8a6..98c16ff32 100644 --- a/cluster.go +++ b/cluster.go @@ -156,13 +156,12 @@ func (opt *ClusterOptions) init() { // names will be treated as unknown parameters // - unknown parameter names will result in an error // Example: -// redis://user:password@localhost:6789?dial_timeout=3&read_timeout=6s&max_retries=2&addr=localhost:6790&addr=localhost:6791 +// redis://user:password@localhost:6789?dial_timeout=3&read_timeout=6s&addr=localhost:6790&addr=localhost:6791 // is equivalent to: // &ClusterOptions{ // Addr: ["localhost:6789", "localhost:6790", "localhost:6791"] // DialTimeout: 3 * time.Second, // no time unit = seconds // ReadTimeout: 6 * time.Second, -// MaxRetries: 2, // } func ParseClusterURL(redisURL string) (*ClusterOptions, error) { o := &ClusterOptions{} From aee0cc6caed486c2053122a6f23774424effd65e Mon Sep 17 00:00:00 2001 From: Stephanie Hingtgen Date: Thu, 21 Oct 2021 14:54:46 -0600 Subject: [PATCH 4/9] feat: add helper func, cleanup code --- cluster.go | 12 +------ cluster_test.go | 84 ++++++++++++++----------------------------------- go.mod | 1 + go.sum | 3 ++ options.go | 44 ++++++++++++++++---------- 5 files changed, 55 insertions(+), 89 deletions(-) diff --git a/cluster.go b/cluster.go index 98c16ff32..3632ce9c2 100644 --- a/cluster.go +++ b/cluster.go @@ -173,17 +173,7 @@ func ParseClusterURL(redisURL string) (*ClusterOptions, error) { // add base URL to the array of addresses // more addresses may be added through the URL params - h, p, err := net.SplitHostPort(u.Host) - if err != nil { - h = u.Host - } - if h == "" { - h = "localhost" - } - if p == "" { - p = "6379" - } - + h, p := getHostPortWithDefaults(u) o.Addrs = append(o.Addrs, net.JoinHostPort(h, p)) // setup username, password, and other configurations diff --git a/cluster_test.go b/cluster_test.go index f923112d7..92512abd5 100644 --- a/cluster_test.go +++ b/cluster_test.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "net" - "reflect" "strconv" "strings" "sync" @@ -15,6 +14,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/stretchr/testify/assert" "github.com/go-redis/redis/v8" "github.com/go-redis/redis/v8/internal/hashtag" @@ -1300,7 +1300,7 @@ func TestParseClusterURL(t *testing.T) { }, { test: "ParseRedissURL", url: "rediss://localhost:123", - o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, TLSConfig: &tls.Config{ /* no deep comparison */ }}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, TLSConfig: &tls.Config{ServerName: "localhost"}}, }, { test: "MissingRedisPort", url: "redis://localhost", @@ -1308,15 +1308,15 @@ func TestParseClusterURL(t *testing.T) { }, { test: "MissingRedissPort", url: "rediss://localhost", - o: &redis.ClusterOptions{Addrs: []string{"localhost:6379"}, TLSConfig: &tls.Config{ /* no deep comparison */ }}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:6379"}, TLSConfig: &tls.Config{ServerName: "localhost"}}, }, { test: "MultipleRedisURLs", url: "redis://localhost:123?addr=localhost:1234&addr=localhost:12345", - o: &redis.ClusterOptions{Addrs: []string{"localhost:123", "localhost:12345", "localhost:1234"}}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123", "localhost:1234", "localhost:12345"}}, }, { test: "MultipleRedissURLs", url: "rediss://localhost:123?addr=localhost:1234&addr=localhost:12345", - o: &redis.ClusterOptions{Addrs: []string{"localhost:123", "localhost:12345", "localhost:1234"}, TLSConfig: &tls.Config{ /* no deep comparison */ }}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123", "localhost:1234", "localhost:12345"}, TLSConfig: &tls.Config{ServerName: "localhost"}}, }, { test: "OnlyPassword", url: "redis://:bar@localhost:123", @@ -1332,7 +1332,7 @@ func TestParseClusterURL(t *testing.T) { }, { test: "RedissUsernamePassword", url: "rediss://foo:bar@localhost:123?addr=localhost:1234", - o: &redis.ClusterOptions{Addrs: []string{"localhost:123", "localhost:1234"}, Username: "foo", Password: "bar", TLSConfig: &tls.Config{ /* no deep comparison */ }}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123", "localhost:1234"}, Username: "foo", Password: "bar", TLSConfig: &tls.Config{ServerName: "localhost"}}, }, { test: "QueryParameters", url: "redis://localhost:123?read_timeout=2&pool_fifo=true&addr=localhost:1234", @@ -1403,59 +1403,21 @@ func TestParseClusterURL(t *testing.T) { func comprareOptions(t *testing.T, actual, expected *redis.ClusterOptions) { t.Helper() - - if !reflect.DeepEqual(actual.Addrs, expected.Addrs) { - t.Errorf("got %q, want %q", actual.Addrs, expected.Addrs) - } - if actual.TLSConfig == nil && expected.TLSConfig != nil { - t.Errorf("got nil TLSConfig, expected a TLSConfig") - } - if actual.TLSConfig != nil && expected.TLSConfig == nil { - t.Errorf("got TLSConfig, expected no TLSConfig") - } - if actual.Username != expected.Username { - t.Errorf("Username: got %q, expected %q", actual.Username, expected.Username) - } - if actual.Password != expected.Password { - t.Errorf("Password: got %q, expected %q", actual.Password, expected.Password) - } - if actual.MaxRetries != expected.MaxRetries { - t.Errorf("MaxRetries: got %v, expected %v", actual.MaxRetries, expected.MaxRetries) - } - if actual.MinRetryBackoff != expected.MinRetryBackoff { - t.Errorf("MinRetryBackoff: got %v, expected %v", actual.MinRetryBackoff, expected.MinRetryBackoff) - } - if actual.MaxRetryBackoff != expected.MaxRetryBackoff { - t.Errorf("MaxRetryBackoff: got %v, expected %v", actual.MaxRetryBackoff, expected.MaxRetryBackoff) - } - if actual.DialTimeout != expected.DialTimeout { - t.Errorf("DialTimeout: got %v, expected %v", actual.DialTimeout, expected.DialTimeout) - } - if actual.ReadTimeout != expected.ReadTimeout { - t.Errorf("ReadTimeout: got %v, expected %v", actual.ReadTimeout, expected.ReadTimeout) - } - if actual.WriteTimeout != expected.WriteTimeout { - t.Errorf("WriteTimeout: got %v, expected %v", actual.WriteTimeout, expected.WriteTimeout) - } - if actual.PoolFIFO != expected.PoolFIFO { - t.Errorf("PoolFIFO: got %v, expected %v", actual.PoolFIFO, expected.PoolFIFO) - } - if actual.PoolSize != expected.PoolSize { - t.Errorf("PoolSize: got %v, expected %v", actual.PoolSize, expected.PoolSize) - } - if actual.MinIdleConns != expected.MinIdleConns { - t.Errorf("MinIdleConns: got %v, expected %v", actual.MinIdleConns, expected.MinIdleConns) - } - if actual.MaxConnAge != expected.MaxConnAge { - t.Errorf("MaxConnAge: got %v, expected %v", actual.MaxConnAge, expected.MaxConnAge) - } - if actual.PoolTimeout != expected.PoolTimeout { - t.Errorf("PoolTimeout: got %v, expected %v", actual.PoolTimeout, expected.PoolTimeout) - } - if actual.IdleTimeout != expected.IdleTimeout { - t.Errorf("IdleTimeout: got %v, expected %v", actual.IdleTimeout, expected.IdleTimeout) - } - if actual.IdleCheckFrequency != expected.IdleCheckFrequency { - t.Errorf("IdleCheckFrequency: got %v, expected %v", actual.IdleCheckFrequency, expected.IdleCheckFrequency) - } + assert.Equal(t, expected.Addrs, actual.Addrs) + assert.Equal(t, expected.TLSConfig, actual.TLSConfig) + assert.Equal(t, expected.Username, actual.Username) + assert.Equal(t, expected.Password, actual.Password) + assert.Equal(t, expected.MaxRetries, actual.MaxRetries) + assert.Equal(t, expected.MinRetryBackoff, actual.MinRetryBackoff) + assert.Equal(t, expected.MaxRetryBackoff, actual.MaxRetryBackoff) + assert.Equal(t, expected.DialTimeout, actual.DialTimeout) + assert.Equal(t, expected.ReadTimeout, actual.ReadTimeout) + assert.Equal(t, expected.WriteTimeout, actual.WriteTimeout) + assert.Equal(t, expected.PoolFIFO, actual.PoolFIFO) + assert.Equal(t, expected.PoolSize, actual.PoolSize) + assert.Equal(t, expected.MinIdleConns, actual.MinIdleConns) + assert.Equal(t, expected.MaxConnAge, actual.MaxConnAge) + assert.Equal(t, expected.PoolTimeout, actual.PoolTimeout) + assert.Equal(t, expected.IdleTimeout, actual.IdleTimeout) + assert.Equal(t, expected.IdleCheckFrequency, actual.IdleCheckFrequency) } diff --git a/go.mod b/go.mod index 68529135a..d34c75d99 100644 --- a/go.mod +++ b/go.mod @@ -8,4 +8,5 @@ require ( github.com/google/go-cmp v0.5.6 // indirect github.com/onsi/ginkgo v1.16.4 github.com/onsi/gomega v1.16.0 + github.com/stretchr/testify v1.5.1 ) diff --git a/go.sum b/go.sum index d9aec3433..db546ade8 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,7 @@ github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +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/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= @@ -36,8 +37,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.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/options.go b/options.go index ed20c5127..c68b0ad90 100644 --- a/options.go +++ b/options.go @@ -240,16 +240,7 @@ func setupTCPConn(u *url.URL) (*Options, error) { o.Username, o.Password = getUserPassword(u) - h, p, err := net.SplitHostPort(u.Host) - if err != nil { - h = u.Host - } - if h == "" { - h = "localhost" - } - if p == "" { - p = "6379" - } + h, p := getHostPortWithDefaults(u) o.Addr = net.JoinHostPort(h, p) f := strings.FieldsFunc(u.Path, func(r rune) bool { @@ -259,6 +250,7 @@ func setupTCPConn(u *url.URL) (*Options, error) { case 0: o.DB = 0 case 1: + var err error if o.DB, err = strconv.Atoi(f[0]); err != nil { return nil, fmt.Errorf("redis: invalid database number: %q", f[0]) } @@ -273,6 +265,23 @@ func setupTCPConn(u *url.URL) (*Options, error) { return setupConnParams(u, o) } +// getHostPortWithDefaults is a helper function that splits the url into +// a host and a port. If the host is missing, it defaults to localhost +// and if the port is missing, it defaults to 6379 +func getHostPortWithDefaults(u *url.URL) (string, string) { + host, port, err := net.SplitHostPort(u.Host) + if err != nil { + host = u.Host + } + if host == "" { + host = "localhost" + } + if port == "" { + port = "6379" + } + return host, port +} + func setupUnixConn(u *url.URL) (*Options, error) { o := &Options{ Network: "unix", @@ -292,19 +301,20 @@ type queryOptions struct { } func (o *queryOptions) string(name string) string { - vs := o.q[name] - if len(vs) == 0 { + if len(o.q[name]) == 0 { return "" } + // get the first item from the array to return + // and remove it so it isn't processed again + param := o.q[name][0] + o.q[name] = o.q[name][1:] - // enable detection of unknown parameters - if len(vs) > 1 { - o.q[name] = o.q[name][:len(vs)-1] - } else { + // remove the key to enable detection of unknown params + if len(o.q[name]) == 0 { delete(o.q, name) } - return vs[len(vs)-1] + return param } func (o *queryOptions) int(name string) int { From 002143fcee28ff984892b586909aeb83ae19a318 Mon Sep 17 00:00:00 2001 From: Stephanie Hingtgen Date: Thu, 21 Oct 2021 14:59:25 -0600 Subject: [PATCH 5/9] feat: fix linter --- options.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options.go b/options.go index c68b0ad90..faa58c4cc 100644 --- a/options.go +++ b/options.go @@ -267,7 +267,7 @@ func setupTCPConn(u *url.URL) (*Options, error) { // getHostPortWithDefaults is a helper function that splits the url into // a host and a port. If the host is missing, it defaults to localhost -// and if the port is missing, it defaults to 6379 +// and if the port is missing, it defaults to 6379. func getHostPortWithDefaults(u *url.URL) (string, string) { host, port, err := net.SplitHostPort(u.Host) if err != nil { From c0973178753e53d38cd338256f74cc7876844175 Mon Sep 17 00:00:00 2001 From: Stephanie Hingtgen Date: Fri, 22 Oct 2021 08:56:01 -0600 Subject: [PATCH 6/9] feat: add strings function --- cluster.go | 9 ++------- options.go | 20 +++++++++----------- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/cluster.go b/cluster.go index 3632ce9c2..e0ad4ba09 100644 --- a/cluster.go +++ b/cluster.go @@ -233,19 +233,14 @@ func setupClusterQueryParams(u *url.URL, o *ClusterOptions) (*ClusterOptions, er } // addr can be specified as many times as needed - addr := q.string("addr") - for addr != "" { + addrs := q.strings("addr") + for _, addr := range addrs { h, p, err := net.SplitHostPort(addr) if err != nil || h == "" || p == "" { return nil, fmt.Errorf("redis: unable to parse addr param: %s", addr) } o.Addrs = append(o.Addrs, net.JoinHostPort(h, p)) - - addr = q.string("addr") - if q.err != nil { - return nil, q.err - } } // any parameters left? diff --git a/options.go b/options.go index faa58c4cc..7658a75e4 100644 --- a/options.go +++ b/options.go @@ -301,20 +301,18 @@ type queryOptions struct { } func (o *queryOptions) string(name string) string { - if len(o.q[name]) == 0 { + vs := o.q[name] + if len(vs) == 0 { return "" } - // get the first item from the array to return - // and remove it so it isn't processed again - param := o.q[name][0] - o.q[name] = o.q[name][1:] - - // remove the key to enable detection of unknown params - if len(o.q[name]) == 0 { - delete(o.q, name) - } + delete(o.q, name) // enable detection of unknown parameters + return vs[len(vs)-1] +} - return param +func (o *queryOptions) strings(name string) []string { + vs := o.q[name] + delete(o.q, name) + return vs } func (o *queryOptions) int(name string) int { From a4e94b7175cbaa393e1f0070b4b46e06fdec72d4 Mon Sep 17 00:00:00 2001 From: Stephanie Hingtgen Date: Mon, 22 Nov 2021 15:30:07 -0700 Subject: [PATCH 7/9] fix: update go mod --- go.mod | 2 +- go.sum | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index d63923a55..b251c85a8 100644 --- a/go.mod +++ b/go.mod @@ -8,5 +8,5 @@ require ( github.com/google/go-cmp v0.5.6 // indirect github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.17.0 - github.com/stretchr/testify v1.5.1 + github.com/stretchr/testify v1.5.1 ) diff --git a/go.sum b/go.sum index 8869740eb..6fff7fbb4 100644 --- a/go.sum +++ b/go.sum @@ -38,6 +38,7 @@ 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.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= From d001e6455b790b2accefc541ef8269b0de492476 Mon Sep 17 00:00:00 2001 From: Vladimir Mihailenco Date: Thu, 6 Oct 2022 13:11:28 +0300 Subject: [PATCH 8/9] chore: fix merge --- cluster.go | 6 ++---- cluster_test.go | 13 ++++++------- go.mod | 4 ++++ go.sum | 47 ++--------------------------------------------- 4 files changed, 14 insertions(+), 56 deletions(-) diff --git a/cluster.go b/cluster.go index 1d5c7b48f..2759d8fd1 100644 --- a/cluster.go +++ b/cluster.go @@ -223,10 +223,9 @@ func setupClusterQueryParams(u *url.URL, o *ClusterOptions) (*ClusterOptions, er o.PoolFIFO = q.bool("pool_fifo") o.PoolSize = q.int("pool_size") o.MinIdleConns = q.int("min_idle_conns") - o.MaxConnAge = q.duration("max_conn_age") o.PoolTimeout = q.duration("pool_timeout") - o.IdleTimeout = q.duration("idle_timeout") - o.IdleCheckFrequency = q.duration("idle_check_frequency") + o.ConnMaxLifetime = q.duration("conn_max_lifetime") + o.ConnMaxIdleTime = q.duration("conn_max_idle_time") if q.err != nil { return nil, q.err @@ -1657,7 +1656,6 @@ func (c *ClusterClient) SSubscribe(ctx context.Context, channels ...string) *Pub return pubsub } - func (c *ClusterClient) retryBackoff(attempt int) time.Duration { return internal.RetryBackoff(attempt, c.opt.MinRetryBackoff, c.opt.MaxRetryBackoff) } diff --git a/cluster_test.go b/cluster_test.go index e39acbc38..1098ab286 100644 --- a/cluster_test.go +++ b/cluster_test.go @@ -1355,19 +1355,19 @@ func TestParseClusterURL(t *testing.T) { }, { test: "DisabledTimeout", url: "redis://localhost:123?idle_timeout=0", - o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, IdleTimeout: -1}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, ConnMaxIdleTime: -1}, }, { test: "DisabledTimeoutNeg", url: "redis://localhost:123?idle_timeout=-1", - o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, IdleTimeout: -1}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, ConnMaxIdleTime: -1}, }, { test: "UseDefault", url: "redis://localhost:123?idle_timeout=", - o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, IdleTimeout: 0}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, ConnMaxIdleTime: 0}, }, { test: "UseDefaultMissing=", url: "redis://localhost:123?idle_timeout", - o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, IdleTimeout: 0}, + o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, ConnMaxIdleTime: 0}, }, { test: "InvalidQueryAddr", url: "rediss://foo:bar@localhost:123?addr=rediss://foo:barr@localhost:1234", @@ -1431,8 +1431,7 @@ func comprareOptions(t *testing.T, actual, expected *redis.ClusterOptions) { assert.Equal(t, expected.PoolFIFO, actual.PoolFIFO) assert.Equal(t, expected.PoolSize, actual.PoolSize) assert.Equal(t, expected.MinIdleConns, actual.MinIdleConns) - assert.Equal(t, expected.MaxConnAge, actual.MaxConnAge) + assert.Equal(t, expected.ConnMaxLifetime, actual.ConnMaxLifetime) + assert.Equal(t, expected.ConnMaxIdleTime, actual.ConnMaxIdleTime) assert.Equal(t, expected.PoolTimeout, actual.PoolTimeout) - assert.Equal(t, expected.IdleTimeout, actual.IdleTimeout) - assert.Equal(t, expected.IdleCheckFrequency, actual.IdleCheckFrequency) } diff --git a/go.mod b/go.mod index 08694d0ff..bc8294b74 100644 --- a/go.mod +++ b/go.mod @@ -7,15 +7,19 @@ require ( github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.20.2 + github.com/stretchr/testify v1.5.1 ) require ( + github.com/davecgh/go-spew v1.1.1 // indirect github.com/fsnotify/fsnotify v1.4.9 // indirect github.com/google/go-cmp v0.5.8 // indirect github.com/nxadm/tail v1.4.8 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect golang.org/x/text v0.3.7 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect + gopkg.in/yaml.v2 v2.3.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 0137b65cb..6c39f42e0 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,5 @@ github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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= @@ -19,100 +16,63 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 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/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU= -github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= github.com/onsi/gomega v1.20.2 h1:8uQq0zMgLEfa0vRrrBgaJF2gyW9Da9BmfGV+OyUzfkY= github.com/onsi/gomega v1.20.2/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 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= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 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= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 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/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/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= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 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/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -123,10 +83,7 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= @@ -134,7 +91,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 6090af686e6b5cf3b8b28c19dc3360f95624065d Mon Sep 17 00:00:00 2001 From: Vladimir Mihailenco Date: Thu, 6 Oct 2022 13:19:35 +0300 Subject: [PATCH 9/9] chore: remove old options --- cluster_test.go | 8 ++++---- options_test.go | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cluster_test.go b/cluster_test.go index 1098ab286..72938a2ba 100644 --- a/cluster_test.go +++ b/cluster_test.go @@ -1354,19 +1354,19 @@ func TestParseClusterURL(t *testing.T) { o: &redis.ClusterOptions{Addrs: []string{"localhost:123", "localhost:1234"}, ReadTimeout: 2 * time.Second, PoolFIFO: true}, }, { test: "DisabledTimeout", - url: "redis://localhost:123?idle_timeout=0", + url: "redis://localhost:123?conn_max_idle_time=0", o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, ConnMaxIdleTime: -1}, }, { test: "DisabledTimeoutNeg", - url: "redis://localhost:123?idle_timeout=-1", + url: "redis://localhost:123?conn_max_idle_time=-1", o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, ConnMaxIdleTime: -1}, }, { test: "UseDefault", - url: "redis://localhost:123?idle_timeout=", + url: "redis://localhost:123?conn_max_idle_time=", o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, ConnMaxIdleTime: 0}, }, { test: "UseDefaultMissing=", - url: "redis://localhost:123?idle_timeout", + url: "redis://localhost:123?conn_max_idle_time", o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, ConnMaxIdleTime: 0}, }, { test: "InvalidQueryAddr", diff --git a/options_test.go b/options_test.go index f9c69a480..47fa9cbc9 100644 --- a/options_test.go +++ b/options_test.go @@ -46,18 +46,18 @@ func TestParseURL(t *testing.T) { o: &Options{Addr: "localhost:123", DB: 2, ReadTimeout: 2 * time.Second, PoolFIFO: true}, }, { // special case handling for disabled timeouts - url: "redis://localhost:123/?db=2&idle_timeout=0", + url: "redis://localhost:123/?db=2&conn_max_idle_time=0", o: &Options{Addr: "localhost:123", DB: 2, ConnMaxIdleTime: -1}, }, { // negative values disable timeouts as well - url: "redis://localhost:123/?db=2&idle_timeout=-1", + url: "redis://localhost:123/?db=2&conn_max_idle_time=-1", o: &Options{Addr: "localhost:123", DB: 2, ConnMaxIdleTime: -1}, }, { // absent timeout values will use defaults - url: "redis://localhost:123/?db=2&idle_timeout=", + url: "redis://localhost:123/?db=2&conn_max_idle_time=", o: &Options{Addr: "localhost:123", DB: 2, ConnMaxIdleTime: 0}, }, { - url: "redis://localhost:123/?db=2&idle_timeout", // missing "=" at the end + url: "redis://localhost:123/?db=2&conn_max_idle_time", // missing "=" at the end o: &Options{Addr: "localhost:123", DB: 2, ConnMaxIdleTime: 0}, }, { url: "unix:///tmp/redis.sock",