redis_failover 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
data/Changes.md CHANGED
@@ -1,3 +1,8 @@
1
+ 0.9.4
2
+ -----------
3
+ - Preserve original master by reading from existing znode state.
4
+ - Prevent Timeout::Error from bringing down the process (#32) (@eric)
5
+
1
6
  0.9.3
2
7
  -----------
3
8
  - Add lock assert for Node Manager.
@@ -175,13 +175,13 @@ module RedisFailover
175
175
  redis = new_client
176
176
  yield redis
177
177
  end
178
- rescue => ex
178
+ rescue Exception => ex
179
179
  raise NodeUnavailableError, "#{ex.class}: #{ex.message}", ex.backtrace
180
180
  ensure
181
181
  if redis
182
182
  begin
183
183
  redis.client.disconnect
184
- rescue => ex
184
+ rescue Exception => ex
185
185
  raise NodeUnavailableError, "#{ex.class}: #{ex.message}", ex.backtrace
186
186
  end
187
187
  end
@@ -10,7 +10,7 @@ module RedisFailover
10
10
  include Util
11
11
 
12
12
  # Number of seconds to wait before retrying bootstrap process.
13
- TIMEOUT = 5
13
+ TIMEOUT = 3
14
14
  # ZK Errors that the Node Manager cares about.
15
15
  ZK_ERRORS = [
16
16
  ZK::Exceptions::LockAssertionFailedError,
@@ -32,7 +32,6 @@ module RedisFailover
32
32
  @znode = @options[:znode_path] || Util::DEFAULT_ZNODE_PATH
33
33
  @manual_znode = ManualFailover::ZNODE_PATH
34
34
  @mutex = Mutex.new
35
- @shutdown = false
36
35
 
37
36
  # Name for the znode that handles exclusive locking between multiple
38
37
  # Node Manager processes. Whoever holds the lock will be considered
@@ -47,7 +46,6 @@ module RedisFailover
47
46
  #
48
47
  # @note This method does not return until the manager terminates.
49
48
  def start
50
- return if @shutdown
51
49
  @queue = Queue.new
52
50
  @leader = false
53
51
  setup_zk
@@ -63,7 +61,6 @@ module RedisFailover
63
61
  rescue *ZK_ERRORS => ex
64
62
  logger.error("ZK error while attempting to manage nodes: #{ex.inspect}")
65
63
  shutdown
66
- sleep(TIMEOUT)
67
64
  retry
68
65
  end
69
66
 
@@ -78,10 +75,10 @@ module RedisFailover
78
75
 
79
76
  # Performs a graceful shutdown of the manager.
80
77
  def shutdown
81
- @shutdown = true
82
78
  @queue.clear
83
79
  @queue << nil
84
80
  @watchers.each(&:shutdown) if @watchers
81
+ sleep(TIMEOUT)
85
82
  @zk.close! if @zk
86
83
  @zk_lock = nil
87
84
  end
@@ -115,7 +112,7 @@ module RedisFailover
115
112
 
116
113
  # Handles periodic state reports from {RedisFailover::NodeWatcher} instances.
117
114
  def handle_state_reports
118
- while running? && (state_report = @queue.pop)
115
+ while state_report = @queue.pop
119
116
  # Ensure that we still have the master lock.
120
117
  @zk_lock.assert!
121
118
 
@@ -238,9 +235,9 @@ module RedisFailover
238
235
 
239
236
  # Discovers the current master and slave nodes.
240
237
  def discover_nodes
241
- @unavailable = []
242
238
  nodes = @options[:nodes].map { |opts| Node.new(opts) }.uniq
243
- @master = find_master(nodes)
239
+ @master = find_existing_master || find_master(nodes)
240
+ @unavailable = []
244
241
  @slaves = nodes - [@master]
245
242
  logger.info("Managing master (#{@master}) and slaves" +
246
243
  " (#{@slaves.map(&:to_s).join(', ')})")
@@ -249,9 +246,32 @@ module RedisFailover
249
246
  redirect_slaves_to(@master) if @master
250
247
  end
251
248
 
249
+ # Seeds the initial node master from an existing znode config.
250
+ def find_existing_master
251
+ if data = @zk.get(@znode).first
252
+ nodes = symbolize_keys(decode(data))
253
+ master = node_from(nodes[:master])
254
+ logger.info("Master from existing config: #{master || 'none'}")
255
+ master
256
+ end
257
+ rescue ZK::Exceptions::NoNode
258
+ # blank slate, no last known master
259
+ nil
260
+ end
261
+
262
+ # Creates a Node instance from a string.
263
+ #
264
+ # @param [String] node_string a string representation of a node (e.g., host:port)
265
+ # @return [Node] the Node representation
266
+ def node_from(node_string)
267
+ return if node_string.nil?
268
+ host, port = node_string.split(':', 2)
269
+ Node.new(:host => host, :port => port, :password => @options[:password])
270
+ end
271
+
252
272
  # Spawns the {RedisFailover::NodeWatcher} instances for each managed node.
253
273
  def spawn_watchers
254
- @watchers = [@master, @slaves, @unavailable].flatten.map do |node|
274
+ @watchers = [@master, @slaves, @unavailable].flatten.compact.map do |node|
255
275
  NodeWatcher.new(self, node, @options[:max_failures] || 3)
256
276
  end
257
277
  @watchers.each(&:watch)
@@ -385,10 +405,5 @@ module RedisFailover
385
405
  logger.error('Failed to perform manual failover, no candidate found.')
386
406
  end
387
407
  end
388
-
389
- # @return [Boolean] true if still running, false otherwise
390
- def running?
391
- !@shutdown
392
- end
393
408
  end
394
409
  end
@@ -66,7 +66,7 @@ module RedisFailover
66
66
  notify(:unavailable)
67
67
  failures = 0
68
68
  end
69
- rescue => ex
69
+ rescue Exception => ex
70
70
  logger.error("Unexpected error while monitoring node #{@node}: #{ex.inspect}")
71
71
  logger.error(ex.backtrace.join("\n"))
72
72
  end
@@ -1,3 +1,3 @@
1
1
  module RedisFailover
2
- VERSION = '0.9.3'
2
+ VERSION = '0.9.4'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis_failover
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
4
+ version: 0.9.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-29 00:00:00.000000000 Z
12
+ date: 2012-08-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis
@@ -189,7 +189,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
189
189
  version: '0'
190
190
  segments:
191
191
  - 0
192
- hash: -1811569102428626424
192
+ hash: -3042115734438994013
193
193
  required_rubygems_version: !ruby/object:Gem::Requirement
194
194
  none: false
195
195
  requirements:
@@ -198,7 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
198
198
  version: '0'
199
199
  segments:
200
200
  - 0
201
- hash: -1811569102428626424
201
+ hash: -3042115734438994013
202
202
  requirements: []
203
203
  rubyforge_project:
204
204
  rubygems_version: 1.8.23