@@ -540,7 +540,6 @@ func (c *sentinelFailover) MasterAddr(ctx context.Context) (string, error) {
540540 if errors .Is (err , context .Canceled ) || errors .Is (err , context .DeadlineExceeded ) {
541541 return "" , err
542542 }
543- // Continue on other errors
544543 internal .Logger .Printf (ctx , "sentinel: GetMasterAddrByName name=%q failed: %s" ,
545544 c .opt .MasterName , err )
546545 } else {
@@ -558,36 +557,59 @@ func (c *sentinelFailover) MasterAddr(ctx context.Context) (string, error) {
558557 if errors .Is (err , context .Canceled ) || errors .Is (err , context .DeadlineExceeded ) {
559558 return "" , err
560559 }
561- // Continue on other errors
562560 internal .Logger .Printf (ctx , "sentinel: GetMasterAddrByName name=%q failed: %s" ,
563561 c .opt .MasterName , err )
564562 } else {
565563 return addr , nil
566564 }
567565 }
568566
567+ var (
568+ masterAddr string
569+ wg sync.WaitGroup
570+ once sync.Once
571+ done = make (chan struct {})
572+ )
573+
569574 for i , sentinelAddr := range c .sentinelAddrs {
570- sentinel := NewSentinelClient (c .opt .sentinelOptions (sentinelAddr ))
575+ wg .Add (1 )
576+ go func (i int , addr string ) {
577+ defer wg .Done ()
578+ select {
579+ case <- done :
580+ return
581+ default :
582+ sentinelCli := NewSentinelClient (c .opt .sentinelOptions (addr ))
583+ addrVal , err := sentinelCli .GetMasterAddrByName (ctx , c .opt .MasterName ).Result ()
584+ if err != nil {
585+ internal .Logger .Printf (ctx , "sentinel: GetMasterAddrByName addr=%s, master=%q failed: %s" ,
586+ addr , c .opt .MasterName , err )
587+ _ = sentinelCli .Close ()
588+ return
589+ }
571590
572- masterAddr , err := sentinel .GetMasterAddrByName (ctx , c .opt .MasterName ).Result ()
573- if err != nil {
574- _ = sentinel .Close ()
575- if errors .Is (err , context .Canceled ) || errors .Is (err , context .DeadlineExceeded ) {
576- return "" , err
591+ once .Do (func () {
592+ masterAddr = net .JoinHostPort (addrVal [0 ], addrVal [1 ])
593+ // Push working sentinel to the top
594+ c .sentinelAddrs [0 ], c .sentinelAddrs [i ] = c .sentinelAddrs [i ], c .sentinelAddrs [0 ]
595+ c .setSentinel (ctx , sentinelCli )
596+ internal .Logger .Printf (ctx , "sentinel: selected addr=%s masterAddr=%s" , addr , masterAddr )
597+ close (done )
598+ })
577599 }
578- internal .Logger .Printf (ctx , "sentinel: GetMasterAddrByName master=%q failed: %s" ,
579- c .opt .MasterName , err )
580- continue
581- }
600+ }(i , sentinelAddr )
601+ }
582602
583- // Push working sentinel to the top.
584- c .sentinelAddrs [0 ], c .sentinelAddrs [i ] = c .sentinelAddrs [i ], c .sentinelAddrs [0 ]
585- c .setSentinel (ctx , sentinel )
603+ go func () {
604+ wg .Wait ()
605+ once .Do (func () { close (done ) })
606+ }()
586607
587- addr := net .JoinHostPort (masterAddr [0 ], masterAddr [1 ])
588- return addr , nil
589- }
608+ <- done
590609
610+ if masterAddr != "" {
611+ return masterAddr , nil
612+ }
591613 return "" , errors .New ("redis: all sentinels specified in configuration are unreachable" )
592614}
593615
0 commit comments