redis_failover 0.9.2 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Changes.md +4 -0
- data/lib/redis_failover/node_manager.rb +32 -6
- data/lib/redis_failover/version.rb +1 -1
- metadata +4 -4
data/Changes.md
CHANGED
@@ -11,6 +11,12 @@ module RedisFailover
|
|
11
11
|
|
12
12
|
# Number of seconds to wait before retrying bootstrap process.
|
13
13
|
TIMEOUT = 5
|
14
|
+
# ZK Errors that the Node Manager cares about.
|
15
|
+
ZK_ERRORS = [
|
16
|
+
ZK::Exceptions::LockAssertionFailedError,
|
17
|
+
ZK::Exceptions::InterruptedSession,
|
18
|
+
ZKDisconnectedError
|
19
|
+
].freeze
|
14
20
|
|
15
21
|
# Creates a new instance.
|
16
22
|
#
|
@@ -26,6 +32,7 @@ module RedisFailover
|
|
26
32
|
@znode = @options[:znode_path] || Util::DEFAULT_ZNODE_PATH
|
27
33
|
@manual_znode = ManualFailover::ZNODE_PATH
|
28
34
|
@mutex = Mutex.new
|
35
|
+
@shutdown = false
|
29
36
|
|
30
37
|
# Name for the znode that handles exclusive locking between multiple
|
31
38
|
# Node Manager processes. Whoever holds the lock will be considered
|
@@ -40,11 +47,12 @@ module RedisFailover
|
|
40
47
|
#
|
41
48
|
# @note This method does not return until the manager terminates.
|
42
49
|
def start
|
50
|
+
return if @shutdown
|
43
51
|
@queue = Queue.new
|
44
52
|
@leader = false
|
45
53
|
setup_zk
|
46
54
|
logger.info('Waiting to become master Node Manager ...')
|
47
|
-
|
55
|
+
with_lock do
|
48
56
|
@leader = true
|
49
57
|
logger.info('Acquired master Node Manager lock')
|
50
58
|
discover_nodes
|
@@ -52,9 +60,8 @@ module RedisFailover
|
|
52
60
|
spawn_watchers
|
53
61
|
handle_state_reports
|
54
62
|
end
|
55
|
-
rescue
|
63
|
+
rescue *ZK_ERRORS => ex
|
56
64
|
logger.error("ZK error while attempting to manage nodes: #{ex.inspect}")
|
57
|
-
logger.error(ex.backtrace.join("\n"))
|
58
65
|
shutdown
|
59
66
|
sleep(TIMEOUT)
|
60
67
|
retry
|
@@ -71,10 +78,12 @@ module RedisFailover
|
|
71
78
|
|
72
79
|
# Performs a graceful shutdown of the manager.
|
73
80
|
def shutdown
|
81
|
+
@shutdown = true
|
74
82
|
@queue.clear
|
75
83
|
@queue << nil
|
76
84
|
@watchers.each(&:shutdown) if @watchers
|
77
85
|
@zk.close! if @zk
|
86
|
+
@zk_lock = nil
|
78
87
|
end
|
79
88
|
|
80
89
|
private
|
@@ -106,7 +115,10 @@ module RedisFailover
|
|
106
115
|
|
107
116
|
# Handles periodic state reports from {RedisFailover::NodeWatcher} instances.
|
108
117
|
def handle_state_reports
|
109
|
-
while state_report = @queue.pop
|
118
|
+
while running? && (state_report = @queue.pop)
|
119
|
+
# Ensure that we still have the master lock.
|
120
|
+
@zk_lock.assert!
|
121
|
+
|
110
122
|
begin
|
111
123
|
node, state = state_report
|
112
124
|
case state
|
@@ -120,7 +132,7 @@ module RedisFailover
|
|
120
132
|
|
121
133
|
# flush current state
|
122
134
|
write_state
|
123
|
-
rescue
|
135
|
+
rescue *ZK_ERRORS
|
124
136
|
# fail hard if this is a ZK connection-related error
|
125
137
|
raise
|
126
138
|
rescue => ex
|
@@ -155,7 +167,7 @@ module RedisFailover
|
|
155
167
|
reconcile(node)
|
156
168
|
|
157
169
|
# no-op if we already know about this node
|
158
|
-
return if @master == node || @slaves.include?(node)
|
170
|
+
return if @master == node || (@master && @slaves.include?(node))
|
159
171
|
logger.info("Handling available node: #{node}")
|
160
172
|
|
161
173
|
if @master
|
@@ -343,6 +355,15 @@ module RedisFailover
|
|
343
355
|
@zk.set(@znode, encode(current_nodes))
|
344
356
|
end
|
345
357
|
|
358
|
+
# Executes a block wrapped in a ZK exclusive lock.
|
359
|
+
def with_lock
|
360
|
+
@zk_lock = @zk.locker(@lock_path)
|
361
|
+
@zk_lock.lock(true)
|
362
|
+
yield
|
363
|
+
ensure
|
364
|
+
@zk_lock.unlock! if @zk_lock
|
365
|
+
end
|
366
|
+
|
346
367
|
# Schedules a manual failover to a redis node.
|
347
368
|
def schedule_manual_failover
|
348
369
|
return unless @leader
|
@@ -364,5 +385,10 @@ module RedisFailover
|
|
364
385
|
logger.error('Failed to perform manual failover, no candidate found.')
|
365
386
|
end
|
366
387
|
end
|
388
|
+
|
389
|
+
# @return [Boolean] true if still running, false otherwise
|
390
|
+
def running?
|
391
|
+
!@shutdown
|
392
|
+
end
|
367
393
|
end
|
368
394
|
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.
|
4
|
+
version: 0.9.3
|
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-
|
12
|
+
date: 2012-08-29 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: -
|
192
|
+
hash: -1811569102428626424
|
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: -
|
201
|
+
hash: -1811569102428626424
|
202
202
|
requirements: []
|
203
203
|
rubyforge_project:
|
204
204
|
rubygems_version: 1.8.23
|