lib/redis_failover/node.rb in redis_failover-0.8.0 vs lib/redis_failover/node.rb in redis_failover-0.8.1

- old
+ new

@@ -8,30 +8,48 @@ # Maximum amount of time given for any redis operation to complete. # If a redis operation doesn't complete in the alotted time, a # NodeUnavailableError will be raised. MAX_OP_WAIT_TIME = 5 - attr_reader :host, :port + # @return [String] the redis server host + attr_reader :host + # @return [Integer] the redis server port + attr_reader :port + + # Creates a new instance. + # + # @param [Hash] options the options used to create the node + # @option options [String] :host the host of the redis server + # @option options [String] :port the port of the redis server def initialize(options = {}) @host = options.fetch(:host) { raise InvalidNodeError, 'missing host'} @port = Integer(options[:port] || 6379) @password = options[:password] end + # @return [Boolean] true if this node is a master, false otherwise def master? role == 'master' end + # @return [Boolean] true if this node is a slave, false otherwise def slave? !master? end + # Determines if this node is a slave of the given master. + # + # @param [Node] master the master to check + # @return [Boolean] true if slave of master, false otherwise def slave_of?(master) current_master == master end + # Determines current master of this slave. + # + # @return [Node] the node representing the master of this slave def current_master info = fetch_info return unless info[:role] == 'slave' Node.new(:host => info[:master_host], :port => info[:master_port].to_i) end @@ -45,87 +63,113 @@ redis.blpop(wait_key, MAX_OP_WAIT_TIME - 3) redis.del(wait_key) end end + # Wakes up this node by pushing a value to its internal + # queue used by #wait. def wakeup perform_operation do |redis| redis.lpush(wait_key, '1') end end + # Makes this node a slave of the given node. + # + # @param [Node] node the node of which to become a slave def make_slave!(node) perform_operation do |redis| unless slave_of?(node) redis.slaveof(node.host, node.port) logger.info("#{self} is now a slave of #{node}") wakeup end end end + # Makes this node a master node. def make_master! perform_operation do |redis| unless master? redis.slaveof('no', 'one') logger.info("#{self} is now master") wakeup end end end + # @return [String] an inspect string for this node def inspect "<RedisFailover::Node #{to_s}>" end + # @return [String] a friendly string for this node def to_s "#{@host}:#{@port}" end + # Determines if this node is equal to another node. + # + # @param [Node] other the other node to compare + # @return [Boolean] true if equal, false otherwise def ==(other) return false unless Node === other return true if self.equal?(other) [host, port] == [other.host, other.port] end alias_method :eql?, :== + + # @return [Integer] a hash value for this node def hash to_s.hash end + # Fetches information/stats for this node. + # + # @return [Hash] the info for this node def fetch_info perform_operation do |redis| symbolize_keys(redis.info) end end alias_method :ping, :fetch_info + # @return [Boolean] determines if this node prohibits stale reads def prohibits_stale_reads? perform_operation do |redis| redis.config('get', 'slave-serve-stale-data').last == 'no' end end + # @return [Boolean] determines if this node is syncing with its master def syncing_with_master? perform_operation do |redis| fetch_info[:master_sync_in_progress] == '1' end end private + # @return [String] the current role for this node def role fetch_info[:role] end + # @return [String] the name of the wait queue for this node def wait_key @wait_key ||= "_redis_failover_#{SecureRandom.hex(32)}" end + # @return [Redis] a new redis client instance for this node def new_client Redis.new(:host => @host, :password => @password, :port => @port) end + # Safely performs a redis operation within a given timeout window. + # + # @yield [Redis] the redis client to use for the operation + # @raise [NodeUnavailableError] if node is currently unreachable def perform_operation redis = nil Timeout.timeout(MAX_OP_WAIT_TIME) do redis = new_client yield redis