Skip to content

Commit

Permalink
ensure that only currently visible nodes are candidates for failover
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanlecompte committed Oct 8, 2012
1 parent 315eb94 commit ea0125f
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 12 deletions.
3 changes: 0 additions & 3 deletions lib/redis_failover/failover_strategy/latency.rb
Expand Up @@ -5,9 +5,6 @@ class FailoverStrategy
class Latency < FailoverStrategy
# @see RedisFailover::FailoverStrategy#find_candidate
def find_candidate(snapshots)
logger.info('Attempting to find candidate from snapshots:')
logger.info("\n" + snapshots.values.join("\n"))

candidates = {}
snapshots.each do |node, snapshot|
if snapshot.all_available?
Expand Down
21 changes: 18 additions & 3 deletions lib/redis_failover/node_manager.rb
Expand Up @@ -195,7 +195,7 @@ def promote_new_master(snapshots, node = nil)
@master = nil

# make a specific node or selected candidate the new master
candidate = node || @failover_strategy.find_candidate(snapshots)
candidate = node || failover_strategy_candidate(snapshots)

unless candidate
logger.error('Failed to promote a new master, no candidate available.')
Expand Down Expand Up @@ -627,7 +627,7 @@ def perform_manual_failover
snapshots = current_node_snapshots

node = if new_master == ManualFailover::ANY_SLAVE
@failover_strategy.find_candidate(snapshots)
failover_strategy_candidate(snapshots)
else
node_from(new_master)
end
Expand Down Expand Up @@ -672,11 +672,26 @@ def ensure_sufficient_node_managers(snapshots)
end

if currently_sufficient && !@sufficient_node_managers
logger.info("Can see all required Node Managers: #{@required_node_managers}")
logger.info("Required Node Managers are visible: #{@required_node_managers}")
end

@sufficient_node_managers = currently_sufficient
@sufficient_node_managers
end

# Invokes the configured failover strategy.
#
# @param [Hash<Node, NodeSnapshot>] snapshots the node snapshots
# @return [Node] a failover candidate
def failover_strategy_candidate(snapshots)
# only include nodes that this master Node Manager can see
filtered_snapshots = snapshots.select do |node, snapshot|
snapshot.viewable_by?(manager_id)
end

logger.info('Attempting to find candidate from snapshots:')
logger.info("\n" + filtered_snapshots.values.join("\n"))
@failover_strategy.find_candidate(filtered_snapshots)
end
end
end
11 changes: 9 additions & 2 deletions lib/redis_failover/node_snapshot.rb
Expand Up @@ -17,15 +17,22 @@ def initialize(node)

# Declares this node available by the specified node manager.
#
# @param [String] node_manager the znode path for the node manager
# @param [String] node_manager the node manager id
# @param [Integer] latency the latency
def viewable_by(node_manager, latency)
@available[node_manager] = latency
end

# Determines if this node is viewable by a node manager.
#
# @param [String] node_manager the node manager id
def viewable_by?(node_manager)
@available.key?(node_manager)
end

# Declares this node unavailable by the specified node manager.
#
# @param [String] node_manager the znode path for the node manager
# @param [String] node_manager the node manager id
def unviewable_by(node_manager)
@unavailable << node_manager
end
Expand Down
8 changes: 4 additions & 4 deletions spec/support/node_manager_stub.rb
Expand Up @@ -18,10 +18,6 @@ def discover_nodes
@master = master
@slaves = [slave]
@failover_strategy = Object.new
slaves = @slaves
@failover_strategy.define_singleton_method(:find_candidate) do |*args|
slaves.pop
end
@nodes_discovered = true
end

Expand Down Expand Up @@ -78,6 +74,10 @@ def force_syncing(node, serve_stale_reads)
stop_processing
end

def failover_strategy_candidate(snapshots)
@slaves.pop
end

def delete_path(*args); end
def create_path(*args); end
def write_state(*args); end
Expand Down

0 comments on commit ea0125f

Please sign in to comment.