class Async::Redis::SentinelsClient
Public Class Methods
new(master_name, sentinels, role = :master, protocol = Protocol::RESP2, **options)
click to toggle source
# File lib/async/redis/sentinels.rb, line 6 def initialize(master_name, sentinels, role = :master, protocol = Protocol::RESP2, **options) @master_name = master_name @sentinel_endpoints = sentinels.map do |sentinel| Async::IO::Endpoint.tcp(sentinel[:host], sentinel[:port]) end @role = role @protocol = protocol @pool = connect(**options) end
Private Instance Methods
available_slaves(slaves_cmd_reply)
click to toggle source
# File lib/async/redis/sentinels.rb, line 77 def available_slaves(slaves_cmd_reply) # The reply is an array with the format: [field1, value1, field2, # value2, etc.]. # When a slave is marked as down by the sentinel, the "flags" field # (comma-separated array) contains the "s_down" value. slaves_cmd_reply.map { |s| s.each_slice(2).to_h } .reject { |s| s.fetch('flags').split(',').include?('s_down') } end
connect(**options)
click to toggle source
Override the parent method. The only difference is that this one needs to resolve the master/slave address.
# File lib/async/redis/sentinels.rb, line 21 def connect(**options) Async::Pool::Controller.wrap(**options) do endpoint = resolve_address peer = endpoint.connect stream = IO::Stream.new(peer) @protocol.client(stream) end end
resolve_address()
click to toggle source
# File lib/async/redis/sentinels.rb, line 31 def resolve_address address = case @role when :master then resolve_master when :slave then resolve_slave else raise ArgumentError, "Unknown instance role #{@role}" end address or raise RuntimeError, "Unable to fetch #{@role} via Sentinel." end
resolve_master()
click to toggle source
# File lib/async/redis/sentinels.rb, line 41 def resolve_master @sentinel_endpoints.each do |sentinel_endpoint| client = Client.new(sentinel_endpoint) begin address = client.call('sentinel', 'get-master-addr-by-name', @master_name) rescue Errno::ECONNREFUSED next end return Async::IO::Endpoint.tcp(address[0], address[1]) if address end nil end
resolve_slave()
click to toggle source
# File lib/async/redis/sentinels.rb, line 57 def resolve_slave @sentinel_endpoints.each do |sentinel_endpoint| client = Client.new(sentinel_endpoint) begin reply = client.call('sentinel', 'slaves', @master_name) rescue Errno::ECONNREFUSED next end slaves = available_slaves(reply) next if slaves.empty? slave = select_slave(slaves) return Async::IO::Endpoint.tcp(slave['ip'], slave['port']) end nil end
select_slave(available_slaves)
click to toggle source
# File lib/async/redis/sentinels.rb, line 86 def select_slave(available_slaves) available_slaves.sample end