diff --git a/universal.go b/universal.go index 0a25bf22..3d91dd49 100644 --- a/universal.go +++ b/universal.go @@ -154,6 +154,9 @@ func (o *UniversalOptions) Failover() *FailoverOptions { SentinelUsername: o.SentinelUsername, SentinelPassword: o.SentinelPassword, + RouteByLatency: o.RouteByLatency, + RouteRandomly: o.RouteRandomly, + MaxRetries: o.MaxRetries, MinRetryBackoff: o.MinRetryBackoff, MaxRetryBackoff: o.MaxRetryBackoff, @@ -256,14 +259,22 @@ var ( // NewUniversalClient returns a new multi client. The type of the returned client depends // on the following conditions: // -// 1. If the MasterName option is specified, a sentinel-backed FailoverClient is returned. -// 2. if the number of Addrs is two or more, a ClusterClient is returned. -// 3. Otherwise, a single-node Client is returned. +// 1. If the MasterName option is specified with RouteByLatency, RouteRandomly or IsClusterMode, +// a FailoverClusterClient is returned. +// 2. If the MasterName option is specified without RouteByLatency, RouteRandomly or IsClusterMode, +// a sentinel-backed FailoverClient is returned. +// 3. If the number of Addrs is two or more, or IsClusterMode option is specified, +// a ClusterClient is returned. +// 4. Otherwise, a single-node Client is returned. func NewUniversalClient(opts *UniversalOptions) UniversalClient { - if opts.MasterName != "" { + switch { + case opts.MasterName != "" && (opts.RouteByLatency || opts.RouteRandomly || opts.IsClusterMode): + return NewFailoverClusterClient(opts.Failover()) + case opts.MasterName != "": return NewFailoverClient(opts.Failover()) - } else if len(opts.Addrs) > 1 || opts.IsClusterMode { + case len(opts.Addrs) > 1 || opts.IsClusterMode: return NewClusterClient(opts.Cluster()) + default: + return NewClient(opts.Simple()) } - return NewClient(opts.Simple()) } diff --git a/universal_test.go b/universal_test.go index e389fe4f..f965253f 100644 --- a/universal_test.go +++ b/universal_test.go @@ -24,6 +24,16 @@ var _ = Describe("UniversalClient", func() { Expect(client.Ping(ctx).Err()).NotTo(HaveOccurred()) }) + It("should connect to failover cluster", Label("NonRedisEnterprise"), func() { + client = redis.NewUniversalClient(&redis.UniversalOptions{ + MasterName: sentinelName, + RouteRandomly: true, + Addrs: sentinelAddrs, + }) + _, ok := client.(*redis.ClusterClient) + Expect(ok).To(BeTrue(), "expected a ClusterClient") + }) + It("should connect to simple servers", func() { client = redis.NewUniversalClient(&redis.UniversalOptions{ Addrs: []string{redisAddr}, @@ -79,6 +89,7 @@ var _ = Describe("UniversalClient", func() { err = client.Set(ctx, "somekey", "somevalue", 0).Err() Expect(err).To(HaveOccurred()) }) + It("should connect to clusters if IsClusterMode is set even if only a single address is provided", Label("NonRedisEnterprise"), func() { client = redis.NewUniversalClient(&redis.UniversalOptions{ Addrs: []string{cluster.addrs()[0]}, @@ -96,4 +107,3 @@ var _ = Describe("UniversalClient", func() { Expect(client.ClusterSlots(ctx).Val()).To(HaveLen(3)) }) }) -