A Redis Sentinel client for high availability Redis deployments.
Definitionsdef initialize(endpoints, master_name: DEFAULT_MASTER_NAME, role: :master, protocol: Protocol::RESP2, **options)
Create a new instance of the SentinelClient.
Implementationdef initialize(endpoints, master_name: DEFAULT_MASTER_NAME, role: :master, protocol: Protocol::RESP2, **options)
@endpoints = endpoints
@master_name = master_name
@role = role
@protocol = protocol
# A cache of sentinel connections.
@sentinels = {}
@pool = make_pool(**options)
end
attr :master_name
Signature
String
The name of the master instance.
attr :role
Signature
Symbol
The role of the instance that you want to connect to.
def resolve_address(role = @role)
Resolve an address for the specified role.
Signaturerole
Symbol
The role to resolve (:master or :slave).
Endpoint
The resolved endpoint address.
def resolve_address(role = @role)
case role
when :master
resolve_master
when :slave
resolve_slave
else
raise ArgumentError, "Unknown instance role #{role}"
end => address
Console.debug(self, "Resolved #{@role} address: #{address}")
address or raise RuntimeError, "Unable to fetch #{role} via Sentinel."
end
def close
Close the sentinel client and all connections.
Implementationdef close
super
@sentinels.each do |_, client|
client.close
end
end
def failover(name = @master_name)
Initiate a failover for the specified master.
Signaturename
String
The name of the master to failover.
Object
The result of the failover command.
def failover(name = @master_name)
sentinels do |client|
return client.call("SENTINEL", "FAILOVER", name)
end
end
def masters
Get information about all masters.
SignatureArray(Hash)
Array of master information hashes.
def masters
sentinels do |client|
return client.call("SENTINEL", "MASTERS").map{|fields| fields.each_slice(2).to_h}
end
end
def master(name = @master_name)
Get information about a specific master.
Signaturename
String
The name of the master.
Hash
The master information hash.
def master(name = @master_name)
sentinels do |client|
return client.call("SENTINEL", "MASTER", name).each_slice(2).to_h
end
end
def resolve_master
Resolve the master endpoint address.
SignatureEndpoint | Nil
The master endpoint or nil if not found.
def resolve_master
sentinels do |client|
begin
address = client.call("SENTINEL", "GET-MASTER-ADDR-BY-NAME", @master_name)
rescue Errno::ECONNREFUSED
next
end
return Endpoint.remote(address[0], address[1]) if address
end
return nil
end
def resolve_slave
Resolve a slave endpoint address.
SignatureEndpoint | Nil
A slave endpoint or nil if not found.
def resolve_slave
sentinels do |client|
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 Endpoint.remote(slave["ip"], slave["port"])
end
return nil
end
def make_pool(**options)
Override the parent method. The only difference is that this one needs to resolve the master/slave address.
Implementationdef make_pool(**options)
self.assign_default_tags(options[:tags] ||= {})
Async::Pool::Controller.wrap(**options) do
endpoint = resolve_address
peer = endpoint.connect
stream = ::IO::Stream(peer)
@protocol.client(stream)
end
end
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4