diff --git a/cluster.go b/cluster.go index e68cb7ee..af311c93 100644 --- a/cluster.go +++ b/cluster.go @@ -54,10 +54,11 @@ type ClusterOptions struct { OnConnect func(*Conn) error + Password string + MaxRetries int MinRetryBackoff time.Duration MaxRetryBackoff time.Duration - Password string DialTimeout time.Duration ReadTimeout time.Duration diff --git a/internal_test.go b/internal_test.go new file mode 100644 index 00000000..139b290a --- /dev/null +++ b/internal_test.go @@ -0,0 +1,65 @@ +package redis + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("newClusterState", func() { + var state *clusterState + + createClusterState := func(slots []ClusterSlot) *clusterState { + nodes := newClusterNodes(&ClusterOptions{}) + state, err := newClusterState(nodes, slots, "10.10.10.10:1234") + Expect(err).NotTo(HaveOccurred()) + return state + } + + Describe("sorting", func() { + BeforeEach(func() { + state = createClusterState([]ClusterSlot{{ + Start: 1000, + End: 1999, + }, { + Start: 0, + End: 999, + }, { + Start: 2000, + End: 2999, + }}) + }) + + It("sorts slots", func() { + Expect(state.slots).To(Equal([]*clusterSlot{ + {start: 0, end: 999, nodes: nil}, + {start: 1000, end: 1999, nodes: nil}, + {start: 2000, end: 2999, nodes: nil}, + })) + }) + }) + + Describe("loopback", func() { + BeforeEach(func() { + state = createClusterState([]ClusterSlot{{ + Nodes: []ClusterNode{{Addr: "127.0.0.1:7001"}}, + }, { + Nodes: []ClusterNode{{Addr: "127.0.0.1:7002"}}, + }, { + Nodes: []ClusterNode{{Addr: "1.2.3.4:1234"}}, + }, { + Nodes: []ClusterNode{{Addr: ":1234"}}, + }}) + }) + + It("replaces loopback hosts in addresses", func() { + slotAddr := func(slot *clusterSlot) string { + return slot.nodes[0].Client.Options().Addr + } + + Expect(slotAddr(state.slots[0])).To(Equal("10.10.10.10:7001")) + Expect(slotAddr(state.slots[1])).To(Equal("10.10.10.10:7002")) + Expect(slotAddr(state.slots[2])).To(Equal("1.2.3.4:1234")) + Expect(slotAddr(state.slots[3])).To(Equal(":1234")) + }) + }) +}) diff --git a/sentinel.go b/sentinel.go index ef0e4701..c5f71493 100644 --- a/sentinel.go +++ b/sentinel.go @@ -29,13 +29,17 @@ type FailoverOptions struct { Password string DB int - MaxRetries int + MaxRetries int + MinRetryBackoff time.Duration + MaxRetryBackoff time.Duration DialTimeout time.Duration ReadTimeout time.Duration WriteTimeout time.Duration PoolSize int + MinIdleConns int + MaxConnAge time.Duration PoolTimeout time.Duration IdleTimeout time.Duration IdleCheckFrequency time.Duration diff --git a/universal.go b/universal.go index 9e30c81d..a6075624 100644 --- a/universal.go +++ b/universal.go @@ -12,35 +12,38 @@ type UniversalOptions struct { // of cluster/sentinel nodes. Addrs []string - // The sentinel master name. - // Only failover clients. - MasterName string - // Database to be selected after connecting to the server. // Only single-node and failover clients. DB int - // Only cluster clients. - - // Enables read only queries on slave nodes. - ReadOnly bool - - MaxRedirects int - RouteByLatency bool - - // Common options + // Common options. OnConnect func(*Conn) error - MaxRetries int Password string + MaxRetries int + MinRetryBackoff time.Duration + MaxRetryBackoff time.Duration DialTimeout time.Duration ReadTimeout time.Duration WriteTimeout time.Duration PoolSize int + MinIdleConns int + MaxConnAge time.Duration PoolTimeout time.Duration IdleTimeout time.Duration IdleCheckFrequency time.Duration TLSConfig *tls.Config + + // Only cluster clients. + + MaxRedirects int + ReadOnly bool + RouteByLatency bool + RouteRandomly bool + + // The sentinel master name. + // Only failover clients. + MasterName string } func (o *UniversalOptions) cluster() *ClusterOptions { @@ -49,22 +52,31 @@ func (o *UniversalOptions) cluster() *ClusterOptions { } return &ClusterOptions{ - Addrs: o.Addrs, - MaxRedirects: o.MaxRedirects, - RouteByLatency: o.RouteByLatency, - ReadOnly: o.ReadOnly, + Addrs: o.Addrs, + OnConnect: o.OnConnect, + + Password: o.Password, + + MaxRedirects: o.MaxRedirects, + ReadOnly: o.ReadOnly, + RouteByLatency: o.RouteByLatency, + RouteRandomly: o.RouteRandomly, + + MaxRetries: o.MaxRetries, + MinRetryBackoff: o.MinRetryBackoff, + MaxRetryBackoff: o.MaxRetryBackoff, - OnConnect: o.OnConnect, - MaxRetries: o.MaxRetries, - Password: o.Password, DialTimeout: o.DialTimeout, ReadTimeout: o.ReadTimeout, WriteTimeout: o.WriteTimeout, PoolSize: o.PoolSize, + MinIdleConns: o.MinIdleConns, + MaxConnAge: o.MaxConnAge, PoolTimeout: o.PoolTimeout, IdleTimeout: o.IdleTimeout, IdleCheckFrequency: o.IdleCheckFrequency, - TLSConfig: o.TLSConfig, + + TLSConfig: o.TLSConfig, } } @@ -76,19 +88,27 @@ func (o *UniversalOptions) failover() *FailoverOptions { return &FailoverOptions{ SentinelAddrs: o.Addrs, MasterName: o.MasterName, - DB: o.DB, + OnConnect: o.OnConnect, + + DB: o.DB, + Password: o.Password, + + MaxRetries: o.MaxRetries, + MinRetryBackoff: o.MinRetryBackoff, + MaxRetryBackoff: o.MaxRetryBackoff, + + DialTimeout: o.DialTimeout, + ReadTimeout: o.ReadTimeout, + WriteTimeout: o.WriteTimeout, - OnConnect: o.OnConnect, - MaxRetries: o.MaxRetries, - Password: o.Password, - DialTimeout: o.DialTimeout, - ReadTimeout: o.ReadTimeout, - WriteTimeout: o.WriteTimeout, PoolSize: o.PoolSize, + MinIdleConns: o.MinIdleConns, + MaxConnAge: o.MaxConnAge, PoolTimeout: o.PoolTimeout, IdleTimeout: o.IdleTimeout, IdleCheckFrequency: o.IdleCheckFrequency, - TLSConfig: o.TLSConfig, + + TLSConfig: o.TLSConfig, } } @@ -99,20 +119,28 @@ func (o *UniversalOptions) simple() *Options { } return &Options{ - Addr: addr, - DB: o.DB, + Addr: addr, + OnConnect: o.OnConnect, + + DB: o.DB, + Password: o.Password, + + MaxRetries: o.MaxRetries, + MinRetryBackoff: o.MinRetryBackoff, + MaxRetryBackoff: o.MaxRetryBackoff, + + DialTimeout: o.DialTimeout, + ReadTimeout: o.ReadTimeout, + WriteTimeout: o.WriteTimeout, - OnConnect: o.OnConnect, - MaxRetries: o.MaxRetries, - Password: o.Password, - DialTimeout: o.DialTimeout, - ReadTimeout: o.ReadTimeout, - WriteTimeout: o.WriteTimeout, PoolSize: o.PoolSize, + MinIdleConns: o.MinIdleConns, + MaxConnAge: o.MaxConnAge, PoolTimeout: o.PoolTimeout, IdleTimeout: o.IdleTimeout, IdleCheckFrequency: o.IdleCheckFrequency, - TLSConfig: o.TLSConfig, + + TLSConfig: o.TLSConfig, } }