redis_failover 0.5.3 → 0.5.4

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,3 +1,7 @@
1
+ 0.5.4
2
+ -----------
3
+ - No longer use problematic ZK#reopen.
4
+
1
5
  0.5.3
2
6
  -----------
3
7
  - Handle more ZK exceptions as candidates for reconnecting the client on error.
@@ -109,37 +109,37 @@ module RedisFailover
109
109
  private
110
110
 
111
111
  def setup_zookeeper_client
112
- @zkclient = ZkClient.new(@zkservers)
113
- update_znode_timestamp
114
-
115
- # when session expires, purge client list
116
- @zkclient.on_session_expiration do
117
- purge_clients
118
- end
112
+ @zkclient = ZkClient.new(@zkservers) do |client|
113
+ # when session expires, purge client list
114
+ client.on_session_expiration do
115
+ purge_clients
116
+ end
119
117
 
120
- # when we are disconnected, purge client list
121
- @zkclient.event_handler.register_state_handler(:connecting) do
122
- purge_clients
123
- end
118
+ # when we are disconnected, purge client list
119
+ client.event_handler.register_state_handler(:connecting) do
120
+ purge_clients
121
+ end
124
122
 
125
- # when session is recovered, watch again
126
- @zkclient.on_session_recovered do
127
- @zkclient.stat(@znode, :watch => true)
128
- end
123
+ # when session is recovered, watch again
124
+ client.on_session_recovered do
125
+ client.stat(@znode, :watch => true)
126
+ end
129
127
 
130
- # register a watcher for future changes
131
- @zkclient.watcher.register(@znode) do |event|
132
- if event.node_created? || event.node_changed?
133
- update_znode_timestamp
134
- build_clients
135
- elsif event.node_deleted?
136
- update_znode_timestamp
137
- purge_clients
138
- @zkclient.stat(@znode, :watch => true)
139
- else
140
- logger.error("Unknown ZK node event: #{event.inspect}")
128
+ # register a watcher for future changes
129
+ client.watcher.register(@znode) do |event|
130
+ if event.node_created? || event.node_changed?
131
+ update_znode_timestamp
132
+ build_clients
133
+ elsif event.node_deleted?
134
+ update_znode_timestamp
135
+ purge_clients
136
+ client.stat(@znode, :watch => true)
137
+ else
138
+ logger.error("Unknown ZK node event: #{event.inspect}")
139
+ end
141
140
  end
142
141
  end
142
+ update_znode_timestamp
143
143
  end
144
144
 
145
145
  def redis_operation?(method)
@@ -177,8 +177,7 @@ module RedisFailover
177
177
  end
178
178
 
179
179
  def master
180
- master = @lock.synchronize { @master }
181
- if master
180
+ if master = @lock.synchronize { @master }
182
181
  verify_role!(master, :master)
183
182
  return master
184
183
  end
@@ -52,7 +52,7 @@ module RedisFailover
52
52
  perform_operation do |redis|
53
53
  unless slave_of?(master)
54
54
  redis.slaveof(master.host, master.port)
55
- logger.info("#{self} now a slave of master #{master}")
55
+ logger.info("#{self} is now a slave of master #{master}")
56
56
  wakeup
57
57
  end
58
58
  end
@@ -86,9 +86,9 @@ module RedisFailover
86
86
  def handle_syncing(node)
87
87
  reconcile(node)
88
88
 
89
- if node.prohibits_stale_reads?
89
+ if node.syncing_with_master? && node.prohibits_stale_reads?
90
90
  logger.info("Node #{node} not ready yet, still syncing with master.")
91
- @unavailable << node
91
+ force_unavailable_slave(node)
92
92
  return
93
93
  end
94
94
 
@@ -119,45 +119,46 @@ module RedisFailover
119
119
  nodes = @options[:nodes].map { |opts| Node.new(opts) }.uniq
120
120
  raise NoMasterError unless @master = find_master(nodes)
121
121
  @slaves = nodes - [@master]
122
+ logger.info("Managing master (#{@master}) and slaves" +
123
+ " (#{@slaves.map(&:to_s).join(', ')})")
122
124
 
123
125
  # ensure that slaves are correctly pointing to this master
124
126
  redirect_slaves_to_master
125
-
126
- logger.info("Managing master (#{@master}) and slaves" +
127
- " (#{@slaves.map(&:to_s).join(', ')})")
128
127
  end
129
128
 
130
129
  def spawn_watchers
131
- @watchers = [@master, *@slaves].map do |node|
130
+ @watchers = [@master, @slaves, @unavailable].flatten.map do |node|
132
131
  NodeWatcher.new(self, node, @options[:max_failures] || 3)
133
132
  end
134
133
  @watchers.each(&:watch)
135
134
  end
136
135
 
137
136
  def find_master(nodes)
138
- # try to find the master - if the actual master is currently
139
- # down, it will be handled by its watcher
140
137
  nodes.find do |node|
141
138
  begin
142
139
  node.master?
143
140
  rescue NodeUnavailableError
144
- # will eventually be handled by watcher
145
141
  false
146
142
  end
147
143
  end
148
144
  end
149
145
 
150
146
  def redirect_slaves_to_master
151
- # redirect each slave to the current master
152
- @slaves.each do |slave|
147
+ @slaves.dup.each do |slave|
153
148
  begin
154
149
  slave.make_slave!(@master)
155
150
  rescue NodeUnavailableError
156
- # will also be detected by watcher
151
+ logger.info("Failed to redirect unreachable slave #{slave} to master #{@master}")
152
+ force_unavailable_slave(slave)
157
153
  end
158
154
  end
159
155
  end
160
156
 
157
+ def force_unavailable_slave(node)
158
+ @slaves.delete(node)
159
+ @unavailable << node unless @unavailable.include?(node)
160
+ end
161
+
161
162
  # It's possible that a newly available node may have been restarted
162
163
  # and completely lost its dynamically set run-time role by the node
163
164
  # manager. This method ensures that the node resumes its role as
@@ -1,3 +1,3 @@
1
1
  module RedisFailover
2
- VERSION = "0.5.3"
2
+ VERSION = "0.5.4"
3
3
  end
@@ -15,9 +15,18 @@ module RedisFailover
15
15
  ZookeeperExceptions::ZookeeperException::ConnectionClosed,
16
16
  ZookeeperExceptions::ZookeeperException::NotConnected
17
17
  ].freeze
18
+ WRAPPED_ZK_METHODS = [
19
+ :get,
20
+ :set,
21
+ :watcher,
22
+ :event_handler,
23
+ :stat,
24
+ :create,
25
+ :delete].freeze
18
26
 
19
- def initialize(servers)
27
+ def initialize(servers, &setup_block)
20
28
  @servers = servers
29
+ @setup_block = setup_block
21
30
  @lock = Mutex.new
22
31
  build_client
23
32
  end
@@ -32,32 +41,14 @@ module RedisFailover
32
41
  @on_session_recovered = block
33
42
  end
34
43
 
35
- def get(*args, &block)
36
- perform_with_reconnect { @client.get(*args, &block) }
37
- end
38
-
39
- def set(*args, &block)
40
- perform_with_reconnect { @client.set(*args, &block) }
41
- end
42
-
43
- def watcher(*args, &block)
44
- perform_with_reconnect { @client.watcher(*args, &block) }
45
- end
46
-
47
- def event_handler(*args, &block)
48
- perform_with_reconnect { @client.event_handler(*args, &block) }
49
- end
50
-
51
- def stat(*args, &block)
52
- perform_with_reconnect { @client.stat(*args, &block) }
53
- end
54
-
55
- def create(*args, &block)
56
- perform_with_reconnect { @client.create(*args, &block) }
57
- end
58
-
59
- def delete(*args, &block)
60
- perform_with_reconnect { @client.delete(*args, &block) }
44
+ WRAPPED_ZK_METHODS.each do |zk_method|
45
+ class_eval <<-RUBY
46
+ def #{zk_method}(*args, &block)
47
+ perform_with_reconnect do
48
+ @client.#{zk_method}(*args, &block)
49
+ end
50
+ end
51
+ RUBY
61
52
  end
62
53
 
63
54
  private
@@ -83,11 +74,8 @@ module RedisFailover
83
74
 
84
75
  def build_client
85
76
  @lock.synchronize do
86
- if @client
87
- @client.reopen
88
- else
89
- @client = ZK.new(@servers)
90
- end
77
+ @client = ZK.new(@servers)
78
+ @setup_block.call(self) if @setup_block
91
79
  logger.info("Communicating with ZooKeeper servers #{@servers}")
92
80
  end
93
81
  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.5.3
4
+ version: 0.5.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-04-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis
16
- requirement: &70306532639260 !ruby/object:Gem::Requirement
16
+ requirement: &70362366935580 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70306532639260
24
+ version_requirements: *70362366935580
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: redis-namespace
27
- requirement: &70306532638840 !ruby/object:Gem::Requirement
27
+ requirement: &70362366935160 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70306532638840
35
+ version_requirements: *70362366935160
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: multi_json
38
- requirement: &70306532638420 !ruby/object:Gem::Requirement
38
+ requirement: &70362366934740 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70306532638420
46
+ version_requirements: *70362366934740
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: zk
49
- requirement: &70306532638000 !ruby/object:Gem::Requirement
49
+ requirement: &70362366934320 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70306532638000
57
+ version_requirements: *70362366934320
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rake
60
- requirement: &70306532637580 !ruby/object:Gem::Requirement
60
+ requirement: &70362366933900 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70306532637580
68
+ version_requirements: *70362366933900
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
- requirement: &70306532637160 !ruby/object:Gem::Requirement
71
+ requirement: &70362366933480 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,7 +76,7 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70306532637160
79
+ version_requirements: *70362366933480
80
80
  description: Redis Failover is a ZooKeeper-based automatic master/slave failover solution
81
81
  for Ruby
82
82
  email:
@@ -129,7 +129,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
129
129
  version: '0'
130
130
  segments:
131
131
  - 0
132
- hash: -4476900958412029501
132
+ hash: 610999762978001666
133
133
  required_rubygems_version: !ruby/object:Gem::Requirement
134
134
  none: false
135
135
  requirements:
@@ -138,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
138
  version: '0'
139
139
  segments:
140
140
  - 0
141
- hash: -4476900958412029501
141
+ hash: 610999762978001666
142
142
  requirements: []
143
143
  rubyforge_project:
144
144
  rubygems_version: 1.8.16