zk 1.2.0 → 1.3.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/Gemfile +3 -3
- data/README.markdown +8 -0
- data/docs/examples/events_01.rb +4 -1
- data/docs/examples/events_02.rb +5 -1
- data/lib/zk/client/base.rb +41 -7
- data/lib/zk/client/threaded.rb +44 -7
- data/lib/zk/core_ext.rb +1 -0
- data/lib/zk/election.rb +2 -1
- data/lib/zk/event_handler.rb +16 -6
- data/lib/zk/event_handler_subscription/base.rb +0 -12
- data/lib/zk/locker/locker_base.rb +6 -1
- data/lib/zk/message_queue.rb +10 -2
- data/lib/zk/subscription.rb +12 -1
- data/lib/zk/threaded_callback.rb +20 -5
- data/lib/zk/threadpool.rb +42 -11
- data/lib/zk/version.rb +1 -1
- data/lib/zk.rb +4 -1
- data/spec/informal/what-the-fork.rb +4 -1
- data/spec/shared/client_examples.rb +2 -0
- data/spec/support/event_catcher.rb +12 -1
- data/spec/support/pendings.rb +12 -0
- data/spec/zk/client_spec.rb +86 -1
- data/spec/zk/pool_spec.rb +8 -2
- data/spec/zookeeper_spec.rb +4 -1
- data/zk.gemspec +1 -2
- metadata +7 -9
data/Gemfile
CHANGED
@@ -7,9 +7,9 @@ source :rubygems
|
|
7
7
|
# this is the last known commit that we tested against and is passing.
|
8
8
|
# keep closer track of this stuff to make bisecting easier and travis more
|
9
9
|
# accurate
|
10
|
-
|
11
|
-
# git 'git://github.com/slyphon/zookeeper.git', :
|
12
|
-
# gem 'zookeeper', '
|
10
|
+
|
11
|
+
# git 'git://github.com/slyphon/zookeeper.git', :tag => 'dev/zk/00000' do
|
12
|
+
# gem 'zookeeper', '~> 1.0.0'
|
13
13
|
# end
|
14
14
|
|
15
15
|
|
data/README.markdown
CHANGED
@@ -63,6 +63,14 @@ In addition to all of that, I would like to think that the public API the ZK::Cl
|
|
63
63
|
|
64
64
|
## NEWS ##
|
65
65
|
|
66
|
+
### v1.3.0 ###
|
67
|
+
|
68
|
+
Phusion Passenger and Unicorn users are encouraged to upgrade!
|
69
|
+
|
70
|
+
* __fork()__: ZK should now work reliably after a fork() if you call `reopen()` ASAP in the child process (before continuing any ZK work). Additionally, your event-handler (blocks set up with `zk.register`) will still work in the child. You will have to make calls like `zk.stat(path, :watch => true)` to tell ZooKeeper to notify you of events (as the child will have a new session), but everything should work.
|
71
|
+
|
72
|
+
* See the fork-handling documentation [on the wiki](http://github.com/slyphon/zk/wiki/Forking).
|
73
|
+
|
66
74
|
### v1.2.0 ###
|
67
75
|
|
68
76
|
You are __STRONGLY ENCOURAGED__ to go and look at the [CHANGELOG](http://git.io/tPbNBw) from the zookeeper 1.0.0 release
|
data/docs/examples/events_01.rb
CHANGED
data/docs/examples/events_02.rb
CHANGED
data/lib/zk/client/base.rb
CHANGED
@@ -85,7 +85,9 @@ module ZK
|
|
85
85
|
#
|
86
86
|
# @abstract Overridden in subclasses
|
87
87
|
def initialize(host, opts={})
|
88
|
-
#
|
88
|
+
# keep track of the process we were in when we started
|
89
|
+
@host = host
|
90
|
+
@pid = Process.pid
|
89
91
|
end
|
90
92
|
|
91
93
|
private
|
@@ -113,17 +115,40 @@ module ZK
|
|
113
115
|
#
|
114
116
|
# @return [Symbol] state of connection after operation
|
115
117
|
def reopen(timeout=nil)
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
118
|
+
# timeout ||= @session_timeout # XXX: @session_timeout ?
|
119
|
+
# cnx.reopen(timeout)
|
120
|
+
# @threadpool.start!
|
121
|
+
# state
|
120
122
|
end
|
121
123
|
|
122
124
|
# close the underlying connection and clear all pending events.
|
123
125
|
#
|
124
126
|
def close!
|
125
127
|
event_handler.clear!
|
126
|
-
wrap_state_closed_error { cnx.close
|
128
|
+
wrap_state_closed_error { cnx.close if cnx && !cnx.closed? }
|
129
|
+
end
|
130
|
+
|
131
|
+
# Connect to the server/cluster. This is called automatically by the
|
132
|
+
# constructor by default.
|
133
|
+
def connect(opts={})
|
134
|
+
end
|
135
|
+
|
136
|
+
# this method will wait until the underlying connection is connected.
|
137
|
+
# please note that when a connection is established, the underlying
|
138
|
+
# zookeeper gem performs this operation. you should only use this
|
139
|
+
# method if you have received a connecting event and want to wait
|
140
|
+
# until the connection has been re-established.
|
141
|
+
#
|
142
|
+
# this method will block until you reach the connected? state or timeout
|
143
|
+
# seconds have passed. if we enter another state, you will not be
|
144
|
+
# awakened in the current implementation, so this method is somewhat
|
145
|
+
# unsafe.
|
146
|
+
#
|
147
|
+
# use this with caution
|
148
|
+
#
|
149
|
+
# @private
|
150
|
+
def wait_until_connected(timeout=10)
|
151
|
+
cnx.wait_until_connected(timeout)
|
127
152
|
end
|
128
153
|
|
129
154
|
# Create a node with the given path. The node data will be the given data.
|
@@ -718,7 +743,11 @@ module ZK
|
|
718
743
|
num =
|
719
744
|
case level
|
720
745
|
when String, Symbol
|
721
|
-
|
746
|
+
begin
|
747
|
+
ZookeeperBase.const_get(:"ZOO_LOG_LEVEL_#{level.to_s.upcase}")
|
748
|
+
rescue NameError
|
749
|
+
nil
|
750
|
+
end
|
722
751
|
when Integer
|
723
752
|
level
|
724
753
|
end
|
@@ -865,6 +894,11 @@ module ZK
|
|
865
894
|
end
|
866
895
|
|
867
896
|
protected
|
897
|
+
# does the current pid match the one that created us?
|
898
|
+
def forked?
|
899
|
+
Process.pid != @pid
|
900
|
+
end
|
901
|
+
|
868
902
|
# @private
|
869
903
|
def check_rc(hash, inputs=nil)
|
870
904
|
code = hash[:rc]
|
data/lib/zk/client/threaded.rb
CHANGED
@@ -110,9 +110,13 @@ module ZK
|
|
110
110
|
# * see {https://github.com/slyphon/zk/wiki/EventDeliveryModel the wiki} for a
|
111
111
|
# discussion and demonstration of the effect of this setting.
|
112
112
|
#
|
113
|
-
# @option opts [Fixnum] :timeout
|
114
|
-
#
|
115
|
-
#
|
113
|
+
# @option opts [Fixnum] :timeout used as a default for calls to {#reopen}
|
114
|
+
# and {#connect} (including the initial default immediate connection)
|
115
|
+
#
|
116
|
+
# @option opts [true,false] :connect (true) Immediately connect to the
|
117
|
+
# server. It may be useful to pass false if you wish to do callback
|
118
|
+
# setup without passing a block. You must then call {#connect}
|
119
|
+
# explicitly.
|
116
120
|
#
|
117
121
|
# @yield [self] calls the block with the new instance after the event
|
118
122
|
# handler and threadpool have been set up, but before any connections
|
@@ -130,24 +134,57 @@ module ZK
|
|
130
134
|
tp_size = opts.fetch(:threadpool_size, DEFAULT_THREADPOOL_SIZE)
|
131
135
|
@threadpool = Threadpool.new(tp_size)
|
132
136
|
|
133
|
-
@
|
137
|
+
@connection_timeout = opts.fetch(:timeout, DEFAULT_TIMEOUT) # maybe move this into superclass?
|
134
138
|
@event_handler = EventHandler.new(self, opts)
|
135
139
|
|
136
140
|
@reconnect = opts.fetch(:reconnect, true)
|
137
141
|
|
138
|
-
@mutex =
|
142
|
+
@mutex = Monitor.new
|
139
143
|
|
140
144
|
@close_requested = false
|
141
145
|
|
142
146
|
yield self if block_given?
|
143
147
|
|
144
|
-
@
|
148
|
+
@mutex.synchronize do
|
149
|
+
connect if opts.fetch(:connect, true)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# @option opts [Fixnum] :timeout how long we will wait for the connection
|
154
|
+
# to be established. If timeout is nil, we will wait forever: *use
|
155
|
+
# carefully*.
|
156
|
+
def connect(opts={})
|
157
|
+
@mutex.synchronize do
|
158
|
+
return if @cnx
|
159
|
+
timeout = opts.fetch(:timeout, @connection_timeout)
|
160
|
+
@cnx = create_connection(@host, timeout, @event_handler.get_default_watcher_block)
|
161
|
+
end
|
145
162
|
end
|
146
163
|
|
147
164
|
# (see Base#reopen)
|
148
165
|
def reopen(timeout=nil)
|
166
|
+
# If we've forked, then we can call all sorts of normally dangerous
|
167
|
+
# stuff because we're the only thread.
|
168
|
+
if forked?
|
169
|
+
# ok, just to sanity check here
|
170
|
+
raise "[BUG] we hit the fork-reopening code in JRuby!!" if defined?(::JRUBY_VERSION)
|
171
|
+
|
172
|
+
logger.debug { "#{self.class}##{__method__} reopening everything, fork detected!" }
|
173
|
+
|
174
|
+
@mutex = Monitor.new
|
175
|
+
@threadpool.reopen_after_fork! # prune dead threadpool threads after a fork()
|
176
|
+
@event_handler.reopen_after_fork!
|
177
|
+
@pid = Process.pid
|
178
|
+
|
179
|
+
old_cnx, @cnx = @cnx, nil
|
180
|
+
old_cnx.close! if old_cnx # && !old_cnx.closed?
|
181
|
+
else
|
182
|
+
logger.debug { "#{self.class}##{__method__} not reopening, no fork detected" }
|
183
|
+
end
|
184
|
+
|
149
185
|
@mutex.synchronize { @close_requested = false }
|
150
|
-
|
186
|
+
connect
|
187
|
+
state
|
151
188
|
end
|
152
189
|
|
153
190
|
# (see Base#close!)
|
data/lib/zk/core_ext.rb
CHANGED
data/lib/zk/election.rb
CHANGED
@@ -239,7 +239,8 @@ module ZK
|
|
239
239
|
protected
|
240
240
|
# the inauguration, as it were
|
241
241
|
def acknowledge_win!
|
242
|
-
@zk.create(leader_ack_path, @data, :ephemeral => true)
|
242
|
+
@zk.create(leader_ack_path, @data, :ephemeral => true)
|
243
|
+
rescue Exceptions::NodeExists
|
243
244
|
end
|
244
245
|
|
245
246
|
# return the list of ephemeral vote nodes
|
data/lib/zk/event_handler.rb
CHANGED
@@ -32,19 +32,30 @@ module ZK
|
|
32
32
|
# :nodoc:
|
33
33
|
def initialize(zookeeper_client, opts={})
|
34
34
|
@zk = zookeeper_client
|
35
|
-
@callbacks = Hash.new { |h,k| h[k] = [] }
|
36
35
|
|
37
36
|
@thread_opt = opts.fetch(:thread, :single)
|
37
|
+
EventHandlerSubscription.class_for_thread_option(@thread_opt) # this is side-effecty, will raise an ArgumentError if given a bad value.
|
38
38
|
|
39
|
-
|
40
|
-
# value.
|
41
|
-
EventHandlerSubscription.class_for_thread_option(@thread_opt)
|
39
|
+
@mutex = nil
|
42
40
|
|
43
|
-
@
|
41
|
+
@callbacks = Hash.new { |h,k| h[k] = [] }
|
44
42
|
|
45
43
|
@outstanding_watches = VALID_WATCH_TYPES.inject({}) do |h,k|
|
46
44
|
h.tap { |x| x[k] = Set.new }
|
47
45
|
end
|
46
|
+
|
47
|
+
reopen_after_fork!
|
48
|
+
end
|
49
|
+
|
50
|
+
# do not call this method. it is inteded for use only when we've forked and
|
51
|
+
# all other threads are dead.
|
52
|
+
#
|
53
|
+
# @private
|
54
|
+
def reopen_after_fork!
|
55
|
+
logger.debug { "#{self.class}##{__method__} reopening callbacks" }
|
56
|
+
@mutex = Monitor.new
|
57
|
+
@callbacks.values.flatten.each { |cb| cb.reopen_after_fork! if cb.respond_to?(:reopen_after_fork!) }
|
58
|
+
nil
|
48
59
|
end
|
49
60
|
|
50
61
|
# @see ZK::Client::Base#register
|
@@ -292,7 +303,6 @@ module ZK
|
|
292
303
|
end
|
293
304
|
end
|
294
305
|
end
|
295
|
-
|
296
306
|
end # EventHandler
|
297
307
|
end # ZK
|
298
308
|
|
@@ -33,18 +33,6 @@ module ZK
|
|
33
33
|
@interests = prep_interests(opts[:only])
|
34
34
|
end
|
35
35
|
|
36
|
-
# unsubscribe from the path or state you were watching
|
37
|
-
# @see ZK::Client::Base#register
|
38
|
-
# def unsubscribe
|
39
|
-
# @event_handler.unregister(self)
|
40
|
-
# end
|
41
|
-
# alias :unregister :unsubscribe
|
42
|
-
|
43
|
-
# # @private
|
44
|
-
# def call(event)
|
45
|
-
# callback.call(event)
|
46
|
-
# end
|
47
|
-
|
48
36
|
# the Actor returns true for this
|
49
37
|
# @private
|
50
38
|
def async?
|
@@ -256,7 +256,12 @@ module ZK
|
|
256
256
|
def cleanup_lock_path!
|
257
257
|
logger.debug { "removing lock path #{@lock_path}" }
|
258
258
|
zk.delete(@lock_path)
|
259
|
-
|
259
|
+
|
260
|
+
begin
|
261
|
+
zk.delete(root_lock_path)
|
262
|
+
rescue NotEmpty
|
263
|
+
end
|
264
|
+
|
260
265
|
@lock_path = nil
|
261
266
|
end
|
262
267
|
end # LockerBase
|
data/lib/zk/message_queue.rb
CHANGED
@@ -120,9 +120,17 @@ module ZK
|
|
120
120
|
locks << lock
|
121
121
|
end
|
122
122
|
children.each do |path|
|
123
|
-
|
123
|
+
begin
|
124
|
+
@zk.delete("#{full_queue_path}/#{path}")
|
125
|
+
rescue ZK::Exceptions::NoNode
|
126
|
+
end
|
124
127
|
end
|
125
|
-
|
128
|
+
|
129
|
+
begin
|
130
|
+
@zk.delete(full_queue_path)
|
131
|
+
rescue ZK::Exceptions::NoNode
|
132
|
+
end
|
133
|
+
|
126
134
|
locks.each do |lock|
|
127
135
|
lock.unlock!
|
128
136
|
end
|
data/lib/zk/subscription.rb
CHANGED
@@ -20,7 +20,7 @@ module ZK
|
|
20
20
|
raise ArgumentError, "block must repsond_to?(:call)" unless block.respond_to?(:call)
|
21
21
|
@parent = parent
|
22
22
|
@callable = block
|
23
|
-
|
23
|
+
reopen_after_fork!
|
24
24
|
end
|
25
25
|
|
26
26
|
def unregister
|
@@ -33,6 +33,11 @@ module ZK
|
|
33
33
|
callable.call(*args)
|
34
34
|
end
|
35
35
|
|
36
|
+
# @private
|
37
|
+
def reopen_after_fork!
|
38
|
+
@mutex = Monitor.new
|
39
|
+
end
|
40
|
+
|
36
41
|
protected
|
37
42
|
def synchronize
|
38
43
|
@mutex.synchronize { yield }
|
@@ -45,6 +50,7 @@ module ZK
|
|
45
50
|
included do
|
46
51
|
alias_method_chain :unsubscribe, :threaded_callback
|
47
52
|
alias_method_chain :callable, :threaded_callback_wrapper
|
53
|
+
alias_method_chain :reopen_after_fork!, :threaded_refresh
|
48
54
|
end
|
49
55
|
|
50
56
|
def unsubscribe_with_threaded_callback
|
@@ -53,6 +59,11 @@ module ZK
|
|
53
59
|
unsubscribe_without_threaded_callback
|
54
60
|
end
|
55
61
|
end
|
62
|
+
|
63
|
+
def reopen_after_fork_with_threaded_refresh!
|
64
|
+
reopen_after_fork_without_threaded_refresh!
|
65
|
+
@threaded_callback = ThreadedCallback.new(@callable)
|
66
|
+
end
|
56
67
|
|
57
68
|
def callable_with_threaded_callback_wrapper(*args)
|
58
69
|
synchronize do
|
data/lib/zk/threaded_callback.rb
CHANGED
@@ -11,9 +11,11 @@ module ZK
|
|
11
11
|
def initialize(callback=nil, &blk)
|
12
12
|
@callback = callback || blk
|
13
13
|
@mutex = Monitor.new
|
14
|
-
|
15
|
-
@
|
16
|
-
|
14
|
+
|
15
|
+
@mutex.synchronize do
|
16
|
+
@running = true
|
17
|
+
reopen_after_fork!
|
18
|
+
end
|
17
19
|
end
|
18
20
|
|
19
21
|
def running?
|
@@ -36,9 +38,22 @@ module ZK
|
|
36
38
|
@queue.push(args)
|
37
39
|
end
|
38
40
|
|
41
|
+
# called after a fork to replace a dead delivery thread
|
42
|
+
# special case, there should be ONLY ONE THREAD RUNNING,
|
43
|
+
# (the one that survived the fork)
|
44
|
+
#
|
45
|
+
# @private
|
46
|
+
def reopen_after_fork!
|
47
|
+
return unless @running
|
48
|
+
return if @thread and @thread.alive?
|
49
|
+
@mutex = Monitor.new
|
50
|
+
@queue = Queue.new
|
51
|
+
@thread = spawn_dispatch_thread()
|
52
|
+
end
|
53
|
+
|
39
54
|
protected
|
40
|
-
def
|
41
|
-
|
55
|
+
def spawn_dispatch_thread
|
56
|
+
Thread.new do
|
42
57
|
while running?
|
43
58
|
args = @queue.pop
|
44
59
|
break if args == KILL_TOKEN
|
data/lib/zk/threadpool.rb
CHANGED
@@ -64,6 +64,17 @@ module ZK
|
|
64
64
|
true
|
65
65
|
end
|
66
66
|
|
67
|
+
# like the start! method, but checks for dead threads in the threadpool
|
68
|
+
# (which will happen after a fork())
|
69
|
+
# @private
|
70
|
+
def reopen_after_fork!
|
71
|
+
return false unless @running
|
72
|
+
@mutex = Monitor.new
|
73
|
+
@threadqueue = Queue.new
|
74
|
+
prune_dead_threads
|
75
|
+
spawn_threadpool
|
76
|
+
end
|
77
|
+
|
67
78
|
# register a block to be called back with unhandled exceptions that occur
|
68
79
|
# in the threadpool.
|
69
80
|
#
|
@@ -138,21 +149,41 @@ module ZK
|
|
138
149
|
logger.error { "#{msg}: #{e.to_std_format}" }
|
139
150
|
end
|
140
151
|
|
141
|
-
def
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
dispatch_to_error_handler(e)
|
152
|
+
def prune_dead_threads
|
153
|
+
@mutex.synchronize do
|
154
|
+
threads, @threadpool = @threadpool, []
|
155
|
+
return if threads.empty?
|
156
|
+
|
157
|
+
while th = threads.shift
|
158
|
+
begin
|
159
|
+
if th.join(0).nil?
|
160
|
+
@threadpool << th
|
151
161
|
end
|
162
|
+
rescue Exception => e
|
163
|
+
logger.error { "Caught exception pruning threads in the threadpool" }
|
164
|
+
logger.error { e.to_std_format }
|
152
165
|
end
|
153
166
|
end
|
167
|
+
end
|
168
|
+
end
|
154
169
|
|
155
|
-
|
170
|
+
def spawn_threadpool #:nodoc:
|
171
|
+
@mutex.synchronize do
|
172
|
+
until @threadpool.size >= @size.to_i
|
173
|
+
thread = Thread.new do
|
174
|
+
while @running
|
175
|
+
begin
|
176
|
+
op = @threadqueue.pop
|
177
|
+
break if op == KILL_TOKEN
|
178
|
+
op.call
|
179
|
+
rescue Exception => e
|
180
|
+
dispatch_to_error_handler(e)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
@threadpool << thread
|
186
|
+
end
|
156
187
|
end
|
157
188
|
end
|
158
189
|
end
|
data/lib/zk/version.rb
CHANGED
data/lib/zk.rb
CHANGED
@@ -13,6 +13,9 @@ require 'set'
|
|
13
13
|
require 'time'
|
14
14
|
require 'date'
|
15
15
|
|
16
|
+
module ZK
|
17
|
+
end
|
18
|
+
|
16
19
|
require 'zk/core_ext'
|
17
20
|
require 'zk/logging'
|
18
21
|
require 'zk/exceptions'
|
@@ -44,7 +47,7 @@ module ZK
|
|
44
47
|
end
|
45
48
|
|
46
49
|
unless @logger
|
47
|
-
@logger = Logger.new($stderr).tap { |n| n.level = Logger::ERROR }
|
50
|
+
@logger = Logger.new($stderr).tap { |n| n.level = ENV['ZK_DEBUG'] ? Logger::DEBUG : Logger::ERROR }
|
48
51
|
end
|
49
52
|
|
50
53
|
@default_host = 'localhost' unless @default_host
|
@@ -29,8 +29,18 @@ class EventCatcher
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
def add(
|
32
|
+
def add(*args)
|
33
33
|
synchronize do
|
34
|
+
case args.length
|
35
|
+
when 2
|
36
|
+
sym, obj = args
|
37
|
+
when 1
|
38
|
+
obj = args.first
|
39
|
+
sym = obj.interest_key
|
40
|
+
else
|
41
|
+
raise ArgumentError, "Dunno how to handle args: #{args.inspect}"
|
42
|
+
end
|
43
|
+
|
34
44
|
logger.debug { "adding #{sym.inspect} #{obj.inspect}" }
|
35
45
|
events[sym] << obj
|
36
46
|
cond(sym).broadcast
|
@@ -39,6 +49,7 @@ class EventCatcher
|
|
39
49
|
cond(:all).broadcast
|
40
50
|
end
|
41
51
|
end
|
52
|
+
alias << add
|
42
53
|
|
43
54
|
def wait_for(ev_name, timeout=5)
|
44
55
|
cond(ev_name).wait(timeout)
|
data/spec/support/pendings.rb
CHANGED
@@ -35,6 +35,18 @@ module Pendings
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
+
def pending_rbx(msg)
|
39
|
+
if ZK.rubinius?
|
40
|
+
if block_given?
|
41
|
+
pending(msg) { yield }
|
42
|
+
else
|
43
|
+
pending(msg)
|
44
|
+
end
|
45
|
+
else
|
46
|
+
yield if block_given?
|
47
|
+
end
|
48
|
+
end
|
49
|
+
alias pending_rubinius pending_rbx
|
38
50
|
|
39
51
|
def pending_in_travis(msg)
|
40
52
|
# defined in the somewhat ill-named 00_test_port_attr.rb
|
data/spec/zk/client_spec.rb
CHANGED
@@ -31,5 +31,90 @@ describe ZK::Client::Threaded do
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
|
+
unless defined?(::JRUBY_VERSION)
|
36
|
+
describe :forked do
|
37
|
+
include_context 'connection opts'
|
38
|
+
|
39
|
+
before do
|
40
|
+
@base_path = '/zktests'
|
41
|
+
@pids_root = "#{@base_path}/pid"
|
42
|
+
|
43
|
+
ZK.open(*connection_args) do |z|
|
44
|
+
z.rm_rf(@base_path)
|
45
|
+
z.mkdir_p(@pids_root)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
after do
|
50
|
+
if @pid
|
51
|
+
begin
|
52
|
+
Process.kill('TERM', @pid)
|
53
|
+
pid, st = Process.wait2(@pid)
|
54
|
+
logger.debug { "child #{@pid} exited with status: #{st.inspect}" }
|
55
|
+
rescue Errno::ESRCH
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
@zk.close! if @zk
|
60
|
+
ZK.open(*connection_args) { |z| z.rm_rf(@base_path) }
|
61
|
+
end
|
62
|
+
|
63
|
+
it %[should deliver callbacks in the child] do
|
64
|
+
pending_in_travis "skip this test, flaky in travis"
|
65
|
+
pending_rbx('fails in rubinius') do
|
66
|
+
|
67
|
+
logger.debug { "Process.pid of parent: #{Process.pid}" }
|
68
|
+
|
69
|
+
@zk = ZK.new do |z|
|
70
|
+
z.on_connected do
|
71
|
+
logger.debug { "on_connected fired, writing pid to path #{@pids_root}/#{$$}" }
|
72
|
+
begin
|
73
|
+
z.create("#{@pids_root}/#{Process.pid}", Process.pid.to_s)
|
74
|
+
rescue ZK::Exceptions::NodeExists
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
@parent_pid = $$
|
80
|
+
|
81
|
+
@zk.create("#{@pids_root}/#{$$}", $$.to_s)
|
82
|
+
|
83
|
+
event_catcher = EventCatcher.new
|
84
|
+
|
85
|
+
@zk.register(@pids_root, :only => :child) do |event|
|
86
|
+
event_catcher << event
|
87
|
+
end
|
88
|
+
|
89
|
+
@pid = fork do
|
90
|
+
@zk.reopen
|
91
|
+
@zk.wait_until_connected
|
92
|
+
|
93
|
+
wait_until(3) { @zk.exists?("#{@pids_root}/#{$$}") }
|
94
|
+
|
95
|
+
logger.debug { "in child: child pid path exists?: %p" % [@zk.exists?("#{@pids_root}/#{$$}")] }
|
96
|
+
|
97
|
+
exit! 0
|
98
|
+
end
|
99
|
+
|
100
|
+
_, stat = Process.wait2(@pid)
|
101
|
+
|
102
|
+
stat.should_not be_signaled
|
103
|
+
stat.should be_exited
|
104
|
+
stat.should be_success
|
105
|
+
|
106
|
+
event_catcher.synchronize do
|
107
|
+
unless event_catcher.child.empty?
|
108
|
+
event_catcher.wait_for_child
|
109
|
+
event_catcher.child.should_not be_empty
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
@zk.should be_exists("#{@pids_root}/#{@pid}")
|
114
|
+
|
115
|
+
end
|
116
|
+
end # should deliver callbacks in the child
|
117
|
+
end # forked
|
118
|
+
end # # jruby guard
|
119
|
+
end # ZK::Client::Threaded
|
35
120
|
|
data/spec/zk/pool_spec.rb
CHANGED
@@ -28,7 +28,10 @@ describe ZK::Pool do
|
|
28
28
|
|
29
29
|
report_realtime("closing") do
|
30
30
|
ZK.open("localhost:#{ZK.test_port}") do |zk|
|
31
|
-
|
31
|
+
begin
|
32
|
+
zk.delete('/test_pool')
|
33
|
+
rescue ZK::Exceptions::NoNode
|
34
|
+
end
|
32
35
|
end
|
33
36
|
end
|
34
37
|
end
|
@@ -119,7 +122,10 @@ describe ZK::Pool do
|
|
119
122
|
@path = '/_testWatch'
|
120
123
|
|
121
124
|
@connection_pool.with_connection do |zk|
|
122
|
-
|
125
|
+
begin
|
126
|
+
zk.delete(@path)
|
127
|
+
rescue ZK::Exceptions::NoNode
|
128
|
+
end
|
123
129
|
end
|
124
130
|
|
125
131
|
@connection_pool.with_connection do |zk|
|
data/spec/zookeeper_spec.rb
CHANGED
data/zk.gemspec
CHANGED
@@ -12,8 +12,7 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.summary = %q{A high-level wrapper around the zookeeper driver}
|
13
13
|
s.description = s.summary + "\n"
|
14
14
|
|
15
|
-
|
16
|
-
s.add_runtime_dependency 'zookeeper', '~> 1.0.0.beta.1'
|
15
|
+
s.add_runtime_dependency 'zookeeper', '~> 1.0.2'
|
17
16
|
s.add_runtime_dependency 'backports', '~> 2.5.1'
|
18
17
|
|
19
18
|
s.files = `git ls-files`.split("\n")
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
8
|
+
- 3
|
9
9
|
- 0
|
10
|
-
version: 1.
|
10
|
+
version: 1.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jonathan D. Simms
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2012-05-
|
19
|
+
date: 2012-05-09 00:00:00 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: zookeeper
|
@@ -26,14 +26,12 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
hash:
|
29
|
+
hash: 19
|
30
30
|
segments:
|
31
31
|
- 1
|
32
32
|
- 0
|
33
|
-
-
|
34
|
-
|
35
|
-
- 1
|
36
|
-
version: 1.0.0.beta.1
|
33
|
+
- 2
|
34
|
+
version: 1.0.2
|
37
35
|
type: :runtime
|
38
36
|
version_requirements: *id001
|
39
37
|
- !ruby/object:Gem::Dependency
|