@@ -530,7 +530,8 @@ def check(client); end
530530
531531 class Sentinel < Connector
532532 EXPECTED_ROLES = {
533- "nearest_slave" => "slave"
533+ "nearest_slave" => "slave" ,
534+ "nearest" => "any"
534535 }
535536
536537 def initialize ( options )
@@ -547,14 +548,15 @@ def check(client)
547548 # Check the instance is really of the role we are looking for.
548549 # We can't assume the command is supported since it was introduced
549550 # recently and this client should work with old stuff.
551+ expected_role = EXPECTED_ROLES . fetch ( @role , @role )
550552 begin
551553 role = client . call ( [ :role ] ) [ 0 ]
552554 rescue Redis ::CommandError
553555 # Assume the test is passed if we can't get a reply from ROLE...
554- role = EXPECTED_ROLES . fetch ( @role , @role )
556+ role = expected_role
555557 end
556558
557- if role != EXPECTED_ROLES . fetch ( @role , @role )
559+ if role != expected_role && "any" != expected_role
558560 client . disconnect
559561 raise ConnectionError , "Instance role mismatch. Expected #{ EXPECTED_ROLES . fetch ( @role , @role ) } , got #{ role } ."
560562 end
@@ -566,6 +568,8 @@ def resolve
566568 resolve_master
567569 when "slave"
568570 resolve_slave
571+ when "nearest"
572+ resolve_nearest
569573 when "nearest_slave"
570574 resolve_nearest_slave
571575 else
@@ -629,30 +633,49 @@ def resolve_slave
629633 end
630634 end
631635
636+ def resolve_nearest
637+ resolve_nearest_for [ :master , :slaves ]
638+ end
639+
632640 def resolve_nearest_slave
641+ resolve_nearest_for [ :slaves ]
642+ end
643+
644+ def resolve_nearest_for ( types )
633645 sentinel_detect do |client |
634- if reply = client . call ( [ "sentinel" , "slaves" , @master ] )
635- ok_slaves = reply . map { |r | Hash [ *r ] } . select { |r | r [ "master-link-status" ] == "ok" }
636-
637- ok_slaves . each do |slave |
638- client = Client . new @options . merge (
639- :host => slave [ "ip" ] ,
640- :port => slave [ "port" ] ,
641- :reconnect_attempts => 0
642- )
643- begin
644- client . call [ :ping ]
645- start = Time . now
646- client . call [ :ping ]
647- slave [ "response_time" ] = ( Time . now - start ) . to_f
648- ensure
649- client . disconnect
646+ ok_nodes = [ ]
647+ types . each do |type |
648+ if reply = client . call ( [ "sentinel" , type , @master ] )
649+ reply = [ reply ] if type == :master
650+ ok_nodes += reply . map { |r | Hash [ *r ] } . select do |r |
651+ case type
652+ when :master
653+ r [ "role-reported" ] == "master"
654+ when :slaves
655+ r [ "master-link-status" ] == "ok" && !r . fetch ( "flags" , "" ) . match ( /s_down|disconnected/ )
656+ end
650657 end
651658 end
659+ end
652660
653- slave = ok_slaves . sort_by { |slave | slave [ "response_time" ] } . first
654- { :host => slave . fetch ( "ip" ) , :port => slave . fetch ( "port" ) } if slave
661+ ok_nodes . each do |node |
662+ client = Client . new @options . merge (
663+ :host => node [ "ip" ] ,
664+ :port => node [ "port" ] ,
665+ :reconnect_attempts => 0
666+ )
667+ begin
668+ client . call [ :ping ]
669+ start = Time . now
670+ client . call [ :ping ]
671+ node [ "response_time" ] = ( Time . now - start ) . to_f
672+ ensure
673+ client . disconnect
674+ end
655675 end
676+
677+ node = ok_nodes . sort_by { |node | node [ "response_time" ] } . first
678+ { :host => node . fetch ( "ip" ) , :port => node . fetch ( "port" ) } if node
656679 end
657680 end
658681
0 commit comments