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 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', :ref => 'e8b181a37ee' do
12
- # gem 'zookeeper', '>= 1.0.0.beta.1'
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
@@ -13,7 +13,10 @@ class Events
13
13
  end
14
14
 
15
15
  def run
16
- @zk.delete(@path) rescue ZK::Exceptions::NoNode
16
+ begin
17
+ @zk.delete(@path)
18
+ rescue ZK::Exceptions::NoNode
19
+ end
17
20
 
18
21
  @zk.register(@path) do |event|
19
22
  if event.node_changed? or event.node_created?
@@ -23,7 +23,11 @@ class Events
23
23
  end
24
24
  end
25
25
 
26
- @zk.delete(@path) rescue ZK::Exceptions::NoNode
26
+ begin
27
+ @zk.delete(@path)
28
+ rescue ZK::Exceptions::NoNode
29
+ end
30
+
27
31
  @zk.stat(@path, watch: true)
28
32
  @zk.create(@path, 'Hello, events!')
29
33
 
@@ -85,7 +85,9 @@ module ZK
85
85
  #
86
86
  # @abstract Overridden in subclasses
87
87
  def initialize(host, opts={})
88
- # no-op
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
- timeout ||= @session_timeout # XXX: @session_timeout ?
117
- cnx.reopen(timeout)
118
- @threadpool.start! # restart the threadpool if previously stopped by close!
119
- state
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 unless cnx.closed? }
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
- ZookeeperBase.const_get(:"ZOO_LOG_LEVEL_#{level.to_s.upcase}") rescue NameError
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]
@@ -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 how long we will wait for the connection
114
- # to be established. If timeout is nil, we will wait forever: *use
115
- # carefully*.
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
- @session_timeout = opts.fetch(:timeout, DEFAULT_TIMEOUT) # maybe move this into superclass?
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 = Mutex.new
142
+ @mutex = Monitor.new
139
143
 
140
144
  @close_requested = false
141
145
 
142
146
  yield self if block_given?
143
147
 
144
- @cnx = create_connection(host, @session_timeout, @event_handler.get_default_watcher_block)
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
- super
186
+ connect
187
+ state
151
188
  end
152
189
 
153
190
  # (see Base#close!)
data/lib/zk/core_ext.rb CHANGED
@@ -99,3 +99,4 @@ class ::Module
99
99
  end
100
100
  end
101
101
 
102
+
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) rescue Exceptions::NodeExists
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
@@ -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
- # this is side-effecty, will raise an ArgumentError if given a bad
40
- # value.
41
- EventHandlerSubscription.class_for_thread_option(@thread_opt)
39
+ @mutex = nil
42
40
 
43
- @mutex = Monitor.new
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
- zk.delete(root_lock_path) rescue NotEmpty
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
@@ -120,9 +120,17 @@ module ZK
120
120
  locks << lock
121
121
  end
122
122
  children.each do |path|
123
- @zk.delete("#{full_queue_path}/#{path}") rescue ZK::Exceptions::NoNode
123
+ begin
124
+ @zk.delete("#{full_queue_path}/#{path}")
125
+ rescue ZK::Exceptions::NoNode
126
+ end
124
127
  end
125
- @zk.delete(full_queue_path) rescue ZK::Exceptions::NoNode
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
@@ -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
- @mutex = Monitor.new
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
@@ -11,9 +11,11 @@ module ZK
11
11
  def initialize(callback=nil, &blk)
12
12
  @callback = callback || blk
13
13
  @mutex = Monitor.new
14
- @queue = Queue.new
15
- @running = true
16
- setup_dispatch_thread
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 setup_dispatch_thread
41
- @thread ||= Thread.new do
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 spawn_threadpool #:nodoc:
142
- until @threadpool.size >= @size.to_i
143
- thread = Thread.new do
144
- while @running
145
- begin
146
- op = @threadqueue.pop
147
- break if op == KILL_TOKEN
148
- op.call
149
- rescue Exception => e
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
- @threadpool << thread
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
@@ -1,3 +1,3 @@
1
1
  module ZK
2
- VERSION = "1.2.0"
2
+ VERSION = "1.3.0"
3
3
  end
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
@@ -69,7 +69,10 @@ class WhatTheFork
69
69
  ensure
70
70
  if pid
71
71
  _debug "ensuring #{pid} is really dead"
72
- Process.kill(9, pid) rescue Errno::ESRCH
72
+ begin
73
+ Process.kill(9, pid)
74
+ rescue Errno::ESRCH
75
+ end
73
76
  end
74
77
  end
75
78
 
@@ -239,6 +239,8 @@ shared_examples_for 'client' do
239
239
 
240
240
  logger.debug { "taunt them a second time" }
241
241
  ensure_event_delivery!
242
+
243
+ logger.debug { "events: #{@events.inspect}" }
242
244
  end
243
245
  end
244
246
 
@@ -29,8 +29,18 @@ class EventCatcher
29
29
  end
30
30
  end
31
31
 
32
- def add(sym,obj)
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)
@@ -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
@@ -31,5 +31,90 @@ describe ZK::Client::Threaded do
31
31
  end
32
32
  end
33
33
  end
34
- end
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
- zk.delete('/test_pool') rescue ZK::Exceptions::NoNode
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
- zk.delete(@path) rescue ZK::Exceptions::NoNode
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|
@@ -2,7 +2,10 @@ require 'spec_helper'
2
2
 
3
3
  shared_examples_for 'ZK basic' do
4
4
  before do
5
- @zk.create(@base_path) rescue ZK::Exceptions::NodeExists
5
+ begin
6
+ @zk.create(@base_path)
7
+ rescue ZK::Exceptions::NodeExists
8
+ end
6
9
  end
7
10
 
8
11
  describe ZK, "with no paths" do
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
- # s.add_runtime_dependency 'slyphon-zookeeper', '~> 1.0.0'
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: 31
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
- - 2
8
+ - 3
9
9
  - 0
10
- version: 1.2.0
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-07 00:00:00 Z
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: 1711417137
29
+ hash: 19
30
30
  segments:
31
31
  - 1
32
32
  - 0
33
- - 0
34
- - beta
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