Skip to content

Commit

Permalink
Rename ReadOnly to SlaveOnly and cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
vmihailenco committed Sep 9, 2020
1 parent 6c85ee7 commit 4877841
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 37 deletions.
74 changes: 39 additions & 35 deletions sentinel.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ type FailoverOptions struct {
// Sentinel password from "requirepass <password>" (if enabled) in Sentinel configuration
SentinelPassword string

// Enables read-only commands on slave nodes.
ReadOnly bool
// Route all commands to slave read-only nodes.
SlaveOnly bool

// Following options are copied from Options struct.

Expand Down Expand Up @@ -57,7 +57,7 @@ type FailoverOptions struct {
}

func (opt *FailoverOptions) options() *Options {
return &Options{
redisOpt := &Options{
Addr: "FailoverClient",

Dialer: opt.Dialer,
Expand All @@ -83,13 +83,13 @@ func (opt *FailoverOptions) options() *Options {
MaxConnAge: opt.MaxConnAge,

TLSConfig: opt.TLSConfig,

sentinelReadOnly: opt.ReadOnly,
}
redisOpt.init()
return redisOpt
}

func (opt *FailoverOptions) clusterOptions() *ClusterOptions {
return &ClusterOptions{
clusterOpt := &ClusterOptions{
Dialer: opt.Dialer,
OnConnect: opt.OnConnect,

Expand All @@ -113,25 +113,24 @@ func (opt *FailoverOptions) clusterOptions() *ClusterOptions {

TLSConfig: opt.TLSConfig,
}
clusterOpt.init()
return clusterOpt
}

// NewFailoverClient returns a Redis client that uses Redis Sentinel
// for automatic failover. It's safe for concurrent use by multiple
// goroutines.
func NewFailoverClient(failoverOpt *FailoverOptions) *Client {
opt := failoverOpt.options()
opt.init()

failover := &sentinelFailover{
masterName: failoverOpt.MasterName,
sentinelAddrs: failoverOpt.SentinelAddrs,
sentinelPassword: failoverOpt.SentinelPassword,

opt: opt,
opt: failoverOpt.options(),
}

// TODO: this overwrites original dialer
opt.Dialer = failover.dial
opt := failoverOpt.options()
opt.Dialer = masterSlaveDialer(failover, failoverOpt.SlaveOnly)

connPool := newConnPool(opt)
failover.onFailover = func(ctx context.Context, addr string) {
Expand All @@ -150,8 +149,35 @@ func NewFailoverClient(failoverOpt *FailoverOptions) *Client {
return &c
}

func masterSlaveDialer(
failover *sentinelFailover, slaveOnly bool,
) func(ctx context.Context, network, addr string) (net.Conn, error) {
return func(ctx context.Context, network, _ string) (net.Conn, error) {
var addr string
var err error

if slaveOnly {
addr, err = failover.RandomSlaveAddr(ctx)
} else {
addr, err = failover.MasterAddr(ctx)
if err == nil {
failover.trySwitchMaster(ctx, addr)
}
}

if err != nil {
return nil, err
}
if failover.opt.Dialer != nil {
return failover.opt.Dialer(ctx, network, addr)
}
return net.DialTimeout("tcp", addr, failover.opt.DialTimeout)
}
}

//------------------------------------------------------------------------------

// SentinelClient is a client for a Redis Sentinel.
type SentinelClient struct {
*baseClient
ctx context.Context
Expand Down Expand Up @@ -358,34 +384,12 @@ func (c *sentinelFailover) closeSentinel() error {
return firstErr
}

func (c *sentinelFailover) dial(ctx context.Context, network, _ string) (net.Conn, error) {
var addr string
var err error

if c.opt.sentinelReadOnly {
addr, err = c.RandomSlaveAddr(ctx)
} else {
addr, err = c.MasterAddr(ctx)
if err == nil {
c.trySwitchMaster(ctx, addr)
}
}

if err != nil {
return nil, err
}
if c.opt.Dialer != nil {
return c.opt.Dialer(ctx, network, addr)
}
return net.DialTimeout("tcp", addr, c.opt.DialTimeout)
}

func (c *sentinelFailover) RandomSlaveAddr(ctx context.Context) (string, error) {
addresses, err := c.slaveAddresses(ctx)
if err != nil {
return "", err
}
if len(addresses) < 1 {
if len(addresses) == 0 {
return c.MasterAddr(ctx)
}
return addresses[rand.Intn(len(addresses))], nil
Expand Down
12 changes: 10 additions & 2 deletions sentinel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ var _ = Describe("Sentinel", func() {
Expect(err).NotTo(HaveOccurred())

// Verify.
val, err := sentinelMaster.Get(ctx, "foo").Result()
val, err := client.Get(ctx, "foo").Result()
Expect(err).NotTo(HaveOccurred())
Expect(val).To(Equal("master"))

Expand Down Expand Up @@ -78,6 +78,10 @@ var _ = Describe("Sentinel", func() {
}, "15s", "100ms").Should(Receive(&msg))
Expect(msg.Channel).To(Equal("foo"))
Expect(msg.Payload).To(Equal("hello"))

Expect(sentinelMaster.Close()).NotTo(HaveOccurred())
sentinelMaster, err = startRedis(sentinelMasterPort)
Expect(err).NotTo(HaveOccurred())
})

It("supports DB selection", func() {
Expand Down Expand Up @@ -114,7 +118,7 @@ var _ = Describe("NewFailoverClusterClient", func() {
Expect(err).NotTo(HaveOccurred())

// Verify.
val, err := sentinelMaster.Get(ctx, "foo").Result()
val, err := client.Get(ctx, "foo").Result()
Expect(err).NotTo(HaveOccurred())
Expect(val).To(Equal("master"))

Expand Down Expand Up @@ -164,5 +168,9 @@ var _ = Describe("NewFailoverClusterClient", func() {
}, "15s", "100ms").Should(Receive(&msg))
Expect(msg.Channel).To(Equal("foo"))
Expect(msg.Payload).To(Equal("hello"))

Expect(sentinelMaster.Close()).NotTo(HaveOccurred())
sentinelMaster, err = startRedis(sentinelMasterPort)
Expect(err).NotTo(HaveOccurred())
})
})

0 comments on commit 4877841

Please sign in to comment.