@@ -530,7 +530,8 @@ def check(client); end
530
530
531
531
class Sentinel < Connector
532
532
EXPECTED_ROLES = {
533
- "nearest_slave" => "slave"
533
+ "nearest_slave" => "slave" ,
534
+ "nearest" => "any"
534
535
}
535
536
536
537
def initialize ( options )
@@ -547,14 +548,15 @@ def check(client)
547
548
# Check the instance is really of the role we are looking for.
548
549
# We can't assume the command is supported since it was introduced
549
550
# recently and this client should work with old stuff.
551
+ expected_role = EXPECTED_ROLES . fetch ( @role , @role )
550
552
begin
551
553
role = client . call ( [ :role ] ) [ 0 ]
552
554
rescue Redis ::CommandError
553
555
# 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
555
557
end
556
558
557
- if role != EXPECTED_ROLES . fetch ( @role , @role )
559
+ if role != expected_role && "any" != expected_role
558
560
client . disconnect
559
561
raise ConnectionError , "Instance role mismatch. Expected #{ EXPECTED_ROLES . fetch ( @role , @role ) } , got #{ role } ."
560
562
end
@@ -566,6 +568,8 @@ def resolve
566
568
resolve_master
567
569
when "slave"
568
570
resolve_slave
571
+ when "nearest"
572
+ resolve_nearest
569
573
when "nearest_slave"
570
574
resolve_nearest_slave
571
575
else
@@ -629,30 +633,49 @@ def resolve_slave
629
633
end
630
634
end
631
635
636
+ def resolve_nearest
637
+ resolve_nearest_for [ :master , :slaves ]
638
+ end
639
+
632
640
def resolve_nearest_slave
641
+ resolve_nearest_for [ :slaves ]
642
+ end
643
+
644
+ def resolve_nearest_for ( types )
633
645
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
650
657
end
651
658
end
659
+ end
652
660
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
655
675
end
676
+
677
+ node = ok_nodes . sort_by { |node | node [ "response_time" ] } . first
678
+ { :host => node . fetch ( "ip" ) , :port => node . fetch ( "port" ) } if node
656
679
end
657
680
end
658
681
0 commit comments