Class: RedisFailover::Node

Inherits:
Object
  • Object
show all
Includes:
Util
Defined in:
lib/redis_failover/node.rb

Overview

Represents a redis node (master or slave). Instances of this class are used by the NodeManager and NodeWatcher to manipulate real redis servers.

Constant Summary

MAX_OP_WAIT_TIME =

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.

5

Constants included from Util

Util::CONNECTIVITY_ERRORS, Util::DEFAULT_ROOT_ZNODE_PATH, Util::REDIS_ERRORS, Util::REDIS_READ_OPS, Util::UNSUPPORTED_OPS, Util::ZK_ERRORS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Util

#decode, #different?, #encode, logger, #logger, logger=, #symbolize_keys

Constructor Details

#initialize(options = {}) ⇒ Node

Creates a new instance.

Parameters:

  • options (Hash) (defaults to: {})

    the options used to create the node

Options Hash (options):

  • :host (String)

    the host of the redis server

  • :port (String)

    the port of the redis server

Raises:



24
25
26
27
28
29
# File 'lib/redis_failover/node.rb', line 24

def initialize(options = {})
  @host = options[:host]
  raise InvalidNodeError, 'missing host' if @host.to_s.empty?
  @port = Integer(options[:port] || 6379)
  @password = options[:password]
end

Instance Attribute Details

#hostString (readonly)

Returns the redis server host

Returns:

  • (String)

    the redis server host



14
15
16
# File 'lib/redis_failover/node.rb', line 14

def host
  @host
end

#portInteger (readonly)

Returns the redis server port

Returns:

  • (Integer)

    the redis server port



17
18
19
# File 'lib/redis_failover/node.rb', line 17

def port
  @port
end

Instance Method Details

#==(other) ⇒ Boolean Also known as: eql?

Determines if this node is equal to another node.

Parameters:

  • other (Node)

    the other node to compare

Returns:

  • (Boolean)

    true if equal, false otherwise



115
116
117
118
119
# File 'lib/redis_failover/node.rb', line 115

def ==(other)
  return false unless Node === other
  return true if self.equal?(other)
  [host, port] == [other.host, other.port]
end

#current_masterNode

Determines current master of this slave.

Returns:

  • (Node)

    the node representing the master of this slave



52
53
54
55
56
# File 'lib/redis_failover/node.rb', line 52

def current_master
  info = fetch_info
  return unless info[:role] == 'slave'
  Node.new(:host => info[:master_host], :port => info[:master_port].to_i)
end

#fetch_infoHash Also known as: ping

Fetches information/stats for this node.

Returns:

  • (Hash)

    the info for this node



130
131
132
133
134
# File 'lib/redis_failover/node.rb', line 130

def fetch_info
  perform_operation do |redis|
    symbolize_keys(redis.info)
  end
end

#hashInteger

Returns a hash value for this node

Returns:

  • (Integer)

    a hash value for this node



123
124
125
# File 'lib/redis_failover/node.rb', line 123

def hash
  to_s.hash
end

#inspectString

Returns an inspect string for this node

Returns:

  • (String)

    an inspect string for this node



102
103
104
# File 'lib/redis_failover/node.rb', line 102

def inspect
  "<RedisFailover::Node #{to_s}>"
end

#make_master!Object

Makes this node a master node.



91
92
93
94
95
96
97
98
99
# File 'lib/redis_failover/node.rb', line 91

def make_master!
  perform_operation do |redis|
    unless master?
      redis.slaveof('no', 'one')
      logger.info("#{self} is now master")
      wakeup
    end
  end
end

#make_slave!(node) ⇒ Object

Makes this node a slave of the given node.

Parameters:

  • node (Node)

    the node of which to become a slave



80
81
82
83
84
85
86
87
88
# File 'lib/redis_failover/node.rb', line 80

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

#master?Boolean

Returns true if this node is a master, false otherwise

Returns:

  • (Boolean)

    true if this node is a master, false otherwise



32
33
34
# File 'lib/redis_failover/node.rb', line 32

def master?
  role == 'master'
end

#prohibits_stale_reads?Boolean

Returns determines if this node prohibits stale reads

Returns:

  • (Boolean)

    determines if this node prohibits stale reads



138
139
140
141
142
# File 'lib/redis_failover/node.rb', line 138

def prohibits_stale_reads?
  perform_operation do |redis|
    redis.config('get', 'slave-serve-stale-data').last == 'no'
  end
end

#slave?Boolean

Returns true if this node is a slave, false otherwise

Returns:

  • (Boolean)

    true if this node is a slave, false otherwise



37
38
39
# File 'lib/redis_failover/node.rb', line 37

def slave?
  !master?
end

#slave_of?(master) ⇒ Boolean

Determines if this node is a slave of the given master.

Parameters:

  • master (Node)

    the master to check

Returns:

  • (Boolean)

    true if slave of master, false otherwise



45
46
47
# File 'lib/redis_failover/node.rb', line 45

def slave_of?(master)
  current_master == master
end

#syncing_with_master?Boolean

Returns determines if this node is syncing with its master

Returns:

  • (Boolean)

    determines if this node is syncing with its master



145
146
147
148
149
# File 'lib/redis_failover/node.rb', line 145

def syncing_with_master?
  perform_operation do |redis|
    fetch_info[:master_sync_in_progress] == '1'
  end
end

#to_sString

Returns a friendly string for this node

Returns:

  • (String)

    a friendly string for this node



107
108
109
# File 'lib/redis_failover/node.rb', line 107

def to_s
  "#{@host}:#{@port}"
end

#waitObject

Waits until something interesting happens. If the connection with this node dies, the blpop call will raise an error. If the blpop call returns without error, then this will be due to a graceful shutdown signaled by #wakeup or a timeout.



62
63
64
65
66
67
# File 'lib/redis_failover/node.rb', line 62

def wait
  perform_operation do |redis|
    redis.blpop(wait_key, MAX_OP_WAIT_TIME - 3)
    redis.del(wait_key)
  end
end

#wakeupObject

Wakes up this node by pushing a value to its internal queue used by #wait.



71
72
73
74
75
# File 'lib/redis_failover/node.rb', line 71

def wakeup
  perform_operation do |redis|
    redis.lpush(wait_key, '1')
  end
end