nogara-redis_failover 0.8.11 → 0.9.0

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 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