zk 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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