nogara-redis_failover 0.8.11 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/Changes.md CHANGED
@@ -1,4 +1,4 @@
1
- HEAD
1
+ 0.9.0
2
2
  -----------
3
3
  - Make Node Manager's lock path vary with its main znode. (Bira)
4
4
  - Node Manager's znode for holding current list of redis nodes is no longer ephemeral. This is unnecessary since the current master should only be changed by redis_failover.
@@ -7,6 +7,7 @@ HEAD
7
7
  - Introduce RedisFailover::Client#on_node_change callback notification for when the currently known list of master/slave redis nodes changes.
8
8
  - Added #current_master and #current_slaves to RedisFailover::Client. This is useful for programmatically doing things based on the current master/slaves.
9
9
  - redis_node_manager should start if no redis servers are available (#29)
10
+ - Better handling of ZK session expirations in Node Manager.
10
11
 
11
12
  0.8.9
12
13
  -----------
@@ -44,4 +44,8 @@ module RedisFailover
44
44
  super("Operation `#{operation}` is currently unsupported")
45
45
  end
46
46
  end
47
+
48
+ # Raised when we detect an expired ZK session.
49
+ class ZKDisconnectedError < Error
50
+ end
47
51
  end
@@ -52,7 +52,7 @@ module RedisFailover
52
52
  spawn_watchers
53
53
  handle_state_reports
54
54
  end
55
- rescue ZK::Exceptions::InterruptedSession => ex
55
+ rescue ZK::Exceptions::InterruptedSession, ZKDisconnectedError => ex
56
56
  logger.error("ZK error while attempting to manage nodes: #{ex.inspect}")
57
57
  logger.error(ex.backtrace.join("\n"))
58
58
  shutdown
@@ -83,6 +83,7 @@ module RedisFailover
83
83
  def setup_zk
84
84
  @zk.close! if @zk
85
85
  @zk = ZK.new("#{@options[:zkservers]}#{@options[:chroot] || ''}")
86
+ @zk.on_expired_session { notify_state(:zk_disconnected, nil) }
86
87
 
87
88
  @zk.register(@manual_znode) do |event|
88
89
  @mutex.synchronize do
@@ -106,12 +107,13 @@ module RedisFailover
106
107
  when :available then handle_available(node)
107
108
  when :syncing then handle_syncing(node)
108
109
  when :manual_failover then handle_manual_failover(node)
110
+ when :zk_disconnected then raise ZKDisconnectedError
109
111
  else raise InvalidNodeStateError.new(node, state)
110
112
  end
111
113
 
112
114
  # flush current state
113
115
  write_state
114
- rescue ZK::Exceptions::InterruptedSession
116
+ rescue ZK::Exceptions::InterruptedSession, ZKDisconnectedError
115
117
  # fail hard if this is a ZK connection-related error
116
118
  raise
117
119
  rescue => ex
@@ -10,8 +10,8 @@ module RedisFailover
10
10
  options = CLI.parse(options)
11
11
  @node_manager = NodeManager.new(options)
12
12
  trap_signals
13
- node_manager_thread = Thread.new { @node_manager.start }
14
- node_manager_thread.join
13
+ @node_manager_thread = Thread.new { @node_manager.start }
14
+ @node_manager_thread.join
15
15
  end
16
16
 
17
17
  # Traps shutdown signals.
@@ -20,6 +20,7 @@ module RedisFailover
20
20
  trap(signal) do
21
21
  Util.logger.info('Shutting down ...')
22
22
  @node_manager.shutdown
23
+ @node_manager_thread.join
23
24
  exit(0)
24
25
  end
25
26
  end
@@ -1,3 +1,3 @@
1
1
  module RedisFailover
2
- VERSION = '0.8.11'
2
+ VERSION = '0.9.0'
3
3
  end
@@ -4,8 +4,8 @@ require File.expand_path('../lib/redis_failover/version', __FILE__)
4
4
  Gem::Specification.new do |gem|
5
5
  gem.authors = ["Ryan LeCompte"]
6
6
  gem.email = ["lecompte@gmail.com"]
7
- gem.description = %(Redis Failover is a ZooKeeper-based automatic master/slave failover solution for Ruby)
8
- gem.summary = %(Redis Failover is a ZooKeeper-based automatic master/slave failover solution for Ruby)
7
+ gem.description = %(redis_failover is a ZooKeeper-based automatic master/slave failover solution for Ruby)
8
+ gem.summary = %(redis_failover is a ZooKeeper-based automatic master/slave failover solution for Ruby)
9
9
  gem.homepage = "http://github.com/ryanlecompte/redis_failover"
10
10
 
11
11
  gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
data/spec/client_spec.rb CHANGED
@@ -26,7 +26,7 @@ module RedisFailover
26
26
  end
27
27
 
28
28
  describe Client do
29
- let(:client) { ClientStub.new(:zkservers => 'localhost:9281') }
29
+ let(:client) { ClientStub.new(:zkservers => 'localhost:9281', :safe_mode => true) }
30
30
 
31
31
  describe '#build_clients' do
32
32
  it 'properly parses master' do
@@ -48,14 +48,28 @@ module RedisFailover
48
48
  called.should be_true
49
49
  end
50
50
 
51
- it 'routes read operations to a slave' do
52
- called = false
53
- client.current_slaves.first.change_role_to('slave')
54
- client.current_slaves.first.define_singleton_method(:get) do |*args|
55
- called = true
51
+ context 'with :master_only false' do
52
+ it 'routes read operations to a slave' do
53
+ called = false
54
+ client.current_slaves.first.change_role_to('slave')
55
+ client.current_slaves.first.define_singleton_method(:get) do |*args|
56
+ called = true
57
+ end
58
+ client.get('foo')
59
+ called.should be_true
60
+ end
61
+ end
62
+
63
+ context 'with :master_only true' do
64
+ it 'routes read operations to master' do
65
+ client = ClientStub.new(:zkservers => 'localhost:9281', :master_only => true)
66
+ called = false
67
+ client.current_master.define_singleton_method(:get) do |*args|
68
+ called = true
69
+ end
70
+ client.get('foo')
71
+ called.should be_true
56
72
  end
57
- client.get('foo')
58
- called.should be_true
59
73
  end
60
74
 
61
75
  it 'reconnects when node is unavailable' do
@@ -90,10 +104,21 @@ module RedisFailover
90
104
  expect { client.select }.to raise_error(UnsupportedOperationError)
91
105
  end
92
106
 
93
- it 'attempts ZK reconnect when no communication from Node Manager within certain time window' do
94
- client.instance_variable_set(:@last_znode_timestamp, Time.at(0))
95
- client.should_receive(:build_clients)
96
- client.del('foo')
107
+ context 'with :safe_mode enabled' do
108
+ it 'rebuilds clients when no communication from Node Manager within certain time window' do
109
+ client.instance_variable_set(:@last_znode_timestamp, Time.at(0))
110
+ client.should_receive(:build_clients)
111
+ client.del('foo')
112
+ end
113
+ end
114
+
115
+ context 'with :safe_mode disabled' do
116
+ it 'does not rebuild clients when no communication from Node Manager within certain time window' do
117
+ client = ClientStub.new(:zkservers => 'localhost:9281', :safe_mode => false)
118
+ client.instance_variable_set(:@last_znode_timestamp, Time.at(0))
119
+ client.should_not_receive(:build_clients)
120
+ client.del('foo')
121
+ end
97
122
  end
98
123
  end
99
124
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nogara-redis_failover
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.11
4
+ version: 0.9.0
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-14 00:00:00.000000000 Z
12
+ date: 2012-08-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis
@@ -129,7 +129,7 @@ dependencies:
129
129
  - - ! '>='
130
130
  - !ruby/object:Gem::Version
131
131
  version: '0'
132
- description: Redis Failover is a ZooKeeper-based automatic master/slave failover solution
132
+ description: redis_failover is a ZooKeeper-based automatic master/slave failover solution
133
133
  for Ruby
134
134
  email:
135
135
  - lecompte@gmail.com
@@ -198,7 +198,7 @@ rubyforge_project:
198
198
  rubygems_version: 1.8.24
199
199
  signing_key:
200
200
  specification_version: 3
201
- summary: Redis Failover is a ZooKeeper-based automatic master/slave failover solution
201
+ summary: redis_failover is a ZooKeeper-based automatic master/slave failover solution
202
202
  for Ruby
203
203
  test_files:
204
204
  - spec/cli_spec.rb