redis_failover 0.8.2 → 0.8.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 +6 -0
- data/lib/redis_failover/client.rb +62 -23
- data/lib/redis_failover/version.rb +1 -1
- data/redis_failover.gemspec +1 -1
- data/spec/client_spec.rb +1 -1
- metadata +6 -6
data/Changes.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
0.8.3
|
2
|
+
-----------
|
3
|
+
- Added a way to gracefully shutdown/reconnect a RedisFailover::Client. (#13)
|
4
|
+
- Upgraded to latest ZK version that supports forking.
|
5
|
+
- Handle case where the same RedisFailover::Client is referenced by a #multi block (#14)
|
6
|
+
|
1
7
|
0.8.2
|
2
8
|
-----------
|
3
9
|
- Fix method signature for RedisFailover::Client#respond_to_missing? (#12)
|
@@ -148,6 +148,26 @@ module RedisFailover
|
|
148
148
|
self
|
149
149
|
end
|
150
150
|
|
151
|
+
# Gracefully performs a shutdown of this client. This method is
|
152
|
+
# mostly useful when the client is used in a forking environment.
|
153
|
+
# When a fork occurs, you can call this method in an after_fork hook,
|
154
|
+
# and then create a new instance of the client. The underlying
|
155
|
+
# ZooKeeper client and redis clients will be closed.
|
156
|
+
def shutdown
|
157
|
+
@zk.close! if @zk
|
158
|
+
@zk = nil
|
159
|
+
purge_clients
|
160
|
+
end
|
161
|
+
|
162
|
+
# Reconnect will first perform a shutdown of the underlying redis clients.
|
163
|
+
# Next, it attempts to reopen the ZooKeeper client and re-create the redis
|
164
|
+
# clients after it fetches the most up-to-date list from ZooKeeper.
|
165
|
+
def reconnect
|
166
|
+
purge_clients
|
167
|
+
@zk ? @zk.reopen : setup_zk
|
168
|
+
build_clients
|
169
|
+
end
|
170
|
+
|
151
171
|
private
|
152
172
|
|
153
173
|
# Sets up the underlying ZooKeeper connection.
|
@@ -191,22 +211,13 @@ module RedisFailover
|
|
191
211
|
# @return [Object] the result of dispatching the command
|
192
212
|
def dispatch(method, *args, &block)
|
193
213
|
unless recently_heard_from_node_manager?
|
194
|
-
|
195
|
-
reconnect_zk
|
196
|
-
build_clients
|
197
|
-
end
|
214
|
+
build_clients
|
198
215
|
end
|
199
216
|
|
200
217
|
verify_supported!(method)
|
201
218
|
tries = 0
|
202
219
|
begin
|
203
|
-
|
204
|
-
# send read operations to a slave
|
205
|
-
slave.send(method, *args, &block)
|
206
|
-
else
|
207
|
-
# direct everything else to master
|
208
|
-
master.send(method, *args, &block)
|
209
|
-
end
|
220
|
+
client_for(method).send(method, *args, &block)
|
210
221
|
rescue *CONNECTIVITY_ERRORS => ex
|
211
222
|
logger.error("Error while handling `#{method}` - #{ex.inspect}")
|
212
223
|
logger.error(ex.backtrace.join("\n"))
|
@@ -218,6 +229,12 @@ module RedisFailover
|
|
218
229
|
retry
|
219
230
|
end
|
220
231
|
raise
|
232
|
+
ensure
|
233
|
+
if info = Thread.current[:last_operation_info]
|
234
|
+
if info[:method] == method
|
235
|
+
Thread.current[:last_operation_info] = nil
|
236
|
+
end
|
237
|
+
end
|
221
238
|
end
|
222
239
|
end
|
223
240
|
|
@@ -251,8 +268,6 @@ module RedisFailover
|
|
251
268
|
# The current master/slaves are fetched via ZooKeeper.
|
252
269
|
def build_clients
|
253
270
|
@lock.synchronize do
|
254
|
-
retried = false
|
255
|
-
|
256
271
|
begin
|
257
272
|
nodes = fetch_nodes
|
258
273
|
return unless nodes_changed?(nodes)
|
@@ -263,16 +278,8 @@ module RedisFailover
|
|
263
278
|
new_slaves = new_clients_for(*nodes[:slaves])
|
264
279
|
@master = new_master
|
265
280
|
@slaves = new_slaves
|
266
|
-
rescue
|
267
|
-
|
268
|
-
logger.error(ex.backtrace.join("\n"))
|
269
|
-
|
270
|
-
# when ZK is disconnected, retry once
|
271
|
-
unless retried
|
272
|
-
reconnect_zk
|
273
|
-
retried = true
|
274
|
-
retry
|
275
|
-
end
|
281
|
+
rescue
|
282
|
+
purge_clients
|
276
283
|
raise
|
277
284
|
end
|
278
285
|
end
|
@@ -287,6 +294,10 @@ module RedisFailover
|
|
287
294
|
logger.debug("Fetched nodes: #{nodes}")
|
288
295
|
|
289
296
|
nodes
|
297
|
+
rescue Zookeeper::Exceptions::InheritedConnectionError => ex
|
298
|
+
logger.debug { "Caught #{ex.class} '#{ex.message}' reconstructing the zk instance" }
|
299
|
+
@zk.reopen
|
300
|
+
retry
|
290
301
|
end
|
291
302
|
|
292
303
|
# Builds new Redis clients for the specified nodes.
|
@@ -404,5 +415,33 @@ module RedisFailover
|
|
404
415
|
return false unless @last_znode_timestamp
|
405
416
|
Time.now - @last_znode_timestamp <= ZNODE_UPDATE_TIMEOUT
|
406
417
|
end
|
418
|
+
|
419
|
+
# Returns the client to use for the specified operation.
|
420
|
+
#
|
421
|
+
# @param [Symbol] method the method for which to retrieve a client
|
422
|
+
# @return [Redis] a redis client to use
|
423
|
+
# @note
|
424
|
+
# This method stores the last client/method used to handle the case
|
425
|
+
# where the same RedisFailover::Client instance is referenced by a
|
426
|
+
# block passed to multi.
|
427
|
+
def client_for(method)
|
428
|
+
if info = Thread.current[:last_operation_info]
|
429
|
+
return info[:client]
|
430
|
+
elsif REDIS_READ_OPS.include?(method)
|
431
|
+
# send read operations to a slave
|
432
|
+
Thread.current[:last_operation_info] = {
|
433
|
+
:client => slave,
|
434
|
+
:method => method
|
435
|
+
}
|
436
|
+
else
|
437
|
+
# direct everything else to master
|
438
|
+
Thread.current[:last_operation_info] = {
|
439
|
+
:client => master,
|
440
|
+
:method => method
|
441
|
+
}
|
442
|
+
end
|
443
|
+
|
444
|
+
Thread.current[:last_operation_info][:client]
|
445
|
+
end
|
407
446
|
end
|
408
447
|
end
|
data/redis_failover.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.add_dependency('redis')
|
19
19
|
gem.add_dependency('redis-namespace')
|
20
20
|
gem.add_dependency('multi_json', '~> 1')
|
21
|
-
gem.add_dependency('zk', '~> 1.
|
21
|
+
gem.add_dependency('zk', '~> 1.4')
|
22
22
|
|
23
23
|
gem.add_development_dependency('rake')
|
24
24
|
gem.add_development_dependency('rspec')
|
data/spec/client_spec.rb
CHANGED
@@ -92,7 +92,7 @@ module RedisFailover
|
|
92
92
|
|
93
93
|
it 'attempts ZK reconnect when no communication from Node Manager within certain time window' do
|
94
94
|
client.instance_variable_set(:@last_znode_timestamp, Time.at(0))
|
95
|
-
client.should_receive(:
|
95
|
+
client.should_receive(:build_clients)
|
96
96
|
client.del('foo')
|
97
97
|
end
|
98
98
|
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.8.
|
4
|
+
version: 0.8.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-05-
|
12
|
+
date: 2012-05-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: redis
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
requirements:
|
67
67
|
- - ~>
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: '1.
|
69
|
+
version: '1.4'
|
70
70
|
type: :runtime
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -74,7 +74,7 @@ dependencies:
|
|
74
74
|
requirements:
|
75
75
|
- - ~>
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: '1.
|
77
|
+
version: '1.4'
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
79
|
name: rake
|
80
80
|
requirement: !ruby/object:Gem::Requirement
|
@@ -177,7 +177,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
177
177
|
version: '0'
|
178
178
|
segments:
|
179
179
|
- 0
|
180
|
-
hash: -
|
180
|
+
hash: -651053748036205721
|
181
181
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
182
182
|
none: false
|
183
183
|
requirements:
|
@@ -186,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
186
186
|
version: '0'
|
187
187
|
segments:
|
188
188
|
- 0
|
189
|
-
hash: -
|
189
|
+
hash: -651053748036205721
|
190
190
|
requirements: []
|
191
191
|
rubyforge_project:
|
192
192
|
rubygems_version: 1.8.23
|