Class: Redis::Client::Connector::Sentinel
- Inherits:
-
Redis::Client::Connector
- Object
- Redis::Client::Connector
- Redis::Client::Connector::Sentinel
- Defined in:
- lib/redis/client.rb
Instance Method Summary collapse
- #check(client) ⇒ Object
-
#initialize(options) ⇒ Sentinel
constructor
A new instance of Sentinel.
- #resolve ⇒ Object
- #resolve_master ⇒ Object
- #resolve_slave ⇒ Object
- #sentinel_detect ⇒ Object
Constructor Details
#initialize(options) ⇒ Sentinel
Returns a new instance of Sentinel.
570 571 572 573 574 575 576 577 578 |
# File 'lib/redis/client.rb', line 570 def initialize() super() @options[:db] = DEFAULTS.fetch(:db) @sentinels = @options.delete(:sentinels).dup @role = (@options[:role] || "master").to_s @master = @options[:host] end |
Instance Method Details
#check(client) ⇒ Object
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 |
# File 'lib/redis/client.rb', line 580 def check(client) # Check the instance is really of the role we are looking for. # We can't assume the command is supported since it was introduced # recently and this client should work with old stuff. begin role = client.call([:role])[0] rescue Redis::CommandError # Assume the test is passed if we can't get a reply from ROLE... role = @role end if role != @role client.disconnect raise ConnectionError, "Instance role mismatch. Expected #{@role}, got #{role}." end end |
#resolve ⇒ Object
597 598 599 600 601 602 603 604 605 606 607 608 |
# File 'lib/redis/client.rb', line 597 def resolve result = case @role when "master" resolve_master when "slave" resolve_slave else raise ArgumentError, "Unknown instance role #{@role}" end result || (raise ConnectionError, "Unable to fetch #{@role} via Sentinel.") end |
#resolve_master ⇒ Object
637 638 639 640 641 642 643 |
# File 'lib/redis/client.rb', line 637 def resolve_master sentinel_detect do |client| if reply = client.call(["sentinel", "get-master-addr-by-name", @master]) { host: reply[0], port: reply[1] } end end end |
#resolve_slave ⇒ Object
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 |
# File 'lib/redis/client.rb', line 645 def resolve_slave sentinel_detect do |client| if reply = client.call(["sentinel", "slaves", @master]) slaves = reply.map { |s| s.each_slice(2).to_h } slaves.each { |s| s['flags'] = s.fetch('flags').split(',') } slaves.reject! { |s| s.fetch('flags').include?('s_down') } if slaves.empty? raise CannotConnectError, 'No slaves available.' else slave = slaves.sample { host: slave.fetch('ip'), port: slave.fetch('port') } end end end end |
#sentinel_detect ⇒ Object
610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 |
# File 'lib/redis/client.rb', line 610 def sentinel_detect @sentinels.each do |sentinel| client = Client.new(@options.merge({ host: sentinel[:host] || sentinel["host"], port: sentinel[:port] || sentinel["port"], username: sentinel[:username] || sentinel["username"], password: sentinel[:password] || sentinel["password"], reconnect_attempts: 0 })) begin if result = yield(client) # This sentinel responded. Make sure we ask it first next time. @sentinels.delete(sentinel) @sentinels.unshift(sentinel) return result end rescue BaseConnectionError ensure client.disconnect end end raise CannotConnectError, "No sentinels available." end |