zk-eventmachine 0.2.0.beta.3 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/.dev_extras/rvmrc CHANGED
@@ -1 +1 @@
1
- rvm 1.9.2@zk-em --create
1
+ rvm 1.9.3@zk-em
data/.gitignore CHANGED
@@ -5,5 +5,6 @@ pkg/*
5
5
  .rvmrc
6
6
  .vimrc
7
7
  .rspec
8
- *.log
8
+ *.log*
9
9
  .yardoc
10
+ doc
data/.yardopts ADDED
@@ -0,0 +1,8 @@
1
+ --protected
2
+ --no-private
3
+ --tag hidden_example:Hidden
4
+ --hide-tag hidden_example
5
+ -
6
+ LICENSE
7
+ README.markdown
8
+
data/Gemfile CHANGED
@@ -1,9 +1,21 @@
1
- source 'http://localhost:50000'
1
+ source ENV['MBOX_BUNDLER_SOURCE'] if ENV['MBOX_BUNDLER_SOURCE']
2
2
  source "http://rubygems.org"
3
3
 
4
+ group :test do
5
+ gem 'rspec', '~> 2.8.0'
6
+ gem 'yard', '~> 0.7.0'
7
+ gem 'autotest', '>= 4.4.0'
8
+ gem 'flexmock', '~> 0.8.10'
9
+ gem 'evented-spec','~> 0.9.0'
10
+ end
11
+
12
+ group :development do
13
+ gem 'redcarpet', '~> 2.1.0'
14
+ gem 'rake'
15
+ gem 'pry'
16
+ end
4
17
 
5
18
  # Specify your gem's dependencies in zk-em.gemspec
6
19
  gemspec
7
20
 
8
-
9
21
  # vim:ft=ruby
data/Rakefile CHANGED
@@ -1,2 +1,37 @@
1
1
  require 'bundler'
2
2
  Bundler::GemHelper.install_tasks
3
+
4
+ task :yard do
5
+ Bundler.setup
6
+ require 'yard'
7
+
8
+ YARD::Rake::YardocTask.new(:run_yardoc) do |t|
9
+ t.files = ['lib/**/*.rb']
10
+ end
11
+
12
+ Rake::Task[:run_yardoc].invoke
13
+ end
14
+
15
+ %w[1.8.7 1.9.2 1.9.3 jruby].each do |rvm_ruby|
16
+ gemset_name = 'zk-em'
17
+ ruby_with_gemset = "#{rvm_ruby}@#{gemset_name}"
18
+ create_gemset_name = "mb:#{rvm_ruby}:create_gemset"
19
+ bundle_task_name = "mb:#{rvm_ruby}:bundle_install"
20
+ rspec_task_name = "mb:#{rvm_ruby}:run_rspec"
21
+
22
+ task create_gemset_name do
23
+ sh "rvm #{rvm_ruby} do rvm gemset create #{gemset_name}"
24
+ end
25
+
26
+ task bundle_task_name => create_gemset_name do
27
+ rm_f 'Gemfile.lock'
28
+ sh "rvm #{ruby_with_gemset} do bundle install"
29
+ end
30
+
31
+ task rspec_task_name => bundle_task_name do
32
+ sh "rvm #{ruby_with_gemset} do bundle exec rspec spec --fail-fast"
33
+ end
34
+
35
+ task 'mb:test_all' => rspec_task_name
36
+ end
37
+
@@ -33,6 +33,12 @@ module ZK
33
33
  end
34
34
  end
35
35
 
36
+ # save a context object, used for associating delivered events with the request that created them
37
+ attr_accessor :context
38
+
39
+ # saves the request id of this call
40
+ attr_reader :req_id
41
+
36
42
  def initialize(prok=nil, &block)
37
43
  on_result(prok, &block)
38
44
  end
@@ -49,7 +55,11 @@ module ZK
49
55
  # Checks the return code from the async call. If the return code was not ZOK,
50
56
  # then fire the errbacks and do the node-style error call
51
57
  # otherwise, does nothing
58
+ #
59
+ # in this call we also stash the outgoing req_id so we can sync it up
52
60
  def check_async_rc(hash)
61
+ @req_id = hash[:req_id]
62
+ logger.debug { "#{__method__}: got #{hash.inspect}" }
53
63
  call(hash) unless success?(hash)
54
64
  end
55
65
 
@@ -58,11 +68,11 @@ module ZK
58
68
  # we take the appropriate actions
59
69
  #
60
70
  # delegates to #deferred_style_result and #node_style_result
61
- def call(hash)
62
- # logger.debug { "#{self.class.name}#call hash: #{hash.inspect}" }
71
+ def call(result)
72
+ logger.debug { "\n#{self.class.name}##{__method__}\n\treq_id: #{req_id.inspect}\n\tcontext: #{context.inspect}\n\tresult: #{result.inspect}" }
63
73
  EM.schedule do
64
- deferred_style_result(hash)
65
- node_style_result(hash)
74
+ deferred_style_result(result)
75
+ node_style_result(result)
66
76
  end
67
77
  end
68
78
 
@@ -70,7 +80,7 @@ module ZK
70
80
  #
71
81
  # @param [Hash] hash the result of the async call
72
82
  #
73
- # @returns [true, false] for success, failure
83
+ # @return [true, false] for success, failure
74
84
  def success?(hash)
75
85
  hash[:rc] == Zookeeper::ZOK
76
86
  end
@@ -1,26 +1,67 @@
1
1
  module ZK
2
2
  module ZKEventMachine
3
3
  class Client < ZK::Client::Base
4
+ include Deferred::Accessors
4
5
  include ZK::Logging
5
6
  include Unixisms
6
7
 
7
8
  DEFAULT_TIMEOUT = 10
8
9
 
9
- # allows the synchrony client to muck with this
10
- # @private
11
- attr_writer :event_handler, :synchrony_client
10
+ # If we get a ZK::Exceptions::ConnectionLoss exeption back from any call,
11
+ # or a EXPIRED_SESSION_STATE event, we will call back any handlers registered
12
+ # here with the exception instance as the argument.
13
+ #
14
+ # once this deferred has been fired, it will be replaced with a new
15
+ # deferred, so callbacks must be re-registered, and *should* be
16
+ # re-registered *within* the callback to avoid missing events
17
+ #
18
+ # @method on_connection_lost
19
+ # @return [Deferred::Default]
20
+ deferred_event :connection_lost
21
+
22
+ # Registers a one-shot callback for the ZOO_CONNECTED_STATE event.
23
+ #
24
+ # @note this is experimental currently. This may or may not fire for the *initial* connection.
25
+ # it's purpose is to warn an already-existing client with watches that a connection has been
26
+ # re-established (with session information saved). From the ZooKeeper Programmers' Guide:
27
+ #
28
+ # If you are using watches, you must look for the connected watch event.
29
+ # When a ZooKeeper client disconnects from a server, you will not receive
30
+ # notification of changes until reconnected. If you are watching for a
31
+ # znode to come into existance, you will miss the event if the znode is
32
+ # created and deleted while you are disconnected.
33
+ #
34
+ # once this deferred has been fired, it will be replaced with a new
35
+ # deferred, so callbacks must be re-registered, and *should* be
36
+ # re-registered *within* the callback to avoid missing events
37
+ #
38
+ # @method on_connected
39
+ # @return [Deferred::Default]
40
+ deferred_event :connected
41
+
42
+ # Registers a one-shot callback for the ZOO_CONNECTING_STATE event
43
+ #
44
+ # This event is triggered when we have become disconnected from the
45
+ # cluster and are in the process of reconnecting.
46
+ deferred_event :connecting
47
+
48
+ # called back once the connection has been closed.
49
+ #
50
+ # @method on_close
51
+ # @return [Deferred::Default]
52
+ deferred_event :close
12
53
 
13
54
  # Takes same options as ZK::Client::Base
14
55
  def initialize(host, opts={})
15
56
  @host = host
16
- @close_deferred = Deferred::Default.new
17
- @connection_lost_deferred = Deferred::Default.new
18
- @event_handler = EventHandlerEM.new(self)
57
+ @event_handler = EventHandlerEM.new(self)
58
+ @closing = false
59
+ register_default_event_handlers!
19
60
  end
20
61
 
21
- def on_close(&blk)
22
- @close_deferred.callback(&blk) if blk
23
- @close_deferred
62
+ # @private
63
+ def closing?
64
+ !!@closing
24
65
  end
25
66
 
26
67
  # open a ZK connection, attach it to the reactor.
@@ -28,37 +69,21 @@ module ZK
28
69
  # ready for use
29
70
  def connect(&blk)
30
71
  # XXX: maybe move this into initialize, need to figure out how to schedule it properly
31
- @cnx ||= ZookeeperEM::Client.new(@host, DEFAULT_TIMEOUT, event_handler.get_default_watcher_block)
32
- # @cnx.on_attached do
33
- # $stderr.puts "@cnx, obj_id: %x" % [@cnx.object_id]
34
- # end
72
+ @cnx ||= (
73
+ ZookeeperEM::Client.new(@host, DEFAULT_TIMEOUT, event_handler.get_default_watcher_block)
74
+ )
35
75
  @cnx.on_attached(&blk)
36
76
  end
37
77
 
38
78
  # @private
39
- # XXX: move this down into ZK::Client::Base
40
- def connected?
41
- @cnx and @cnx.connected?
42
- end
43
-
44
- # If we get a ZK::Exceptions::ConnectionLoss exeption back from any call,
45
- # we will call back any handlers registered here with the exception
46
- # instance as the argument
47
- #
48
- # once this deferred has been fired, it will be replaced with a new
49
- # deferred, so callbacks must be re-registered
50
- #
51
- def on_connection_lost(&blk)
52
- @connection_lost_deferred.callback(&blk) if blk
53
- @connection_lost_deferred
54
- end
55
-
56
79
  def reopen(*a)
57
80
  raise NotImplementedError, "reoopen is not implemented for the eventmachine version of the client"
58
81
  end
59
82
 
60
83
  def close!(&blk)
61
84
  on_close(&blk)
85
+ return on_close if @closing
86
+ @closing = true
62
87
 
63
88
  if @cnx
64
89
  logger.debug { "#{self.class.name}: in close! clearing event_handler" }
@@ -66,11 +91,8 @@ module ZK
66
91
 
67
92
  logger.debug { "#{self.class.name}: calling @cnx.close" }
68
93
  @cnx.close do
69
- # fire the on_close handler in next_tick so that @cnx is nil
70
- EM.next_tick do
71
- logger.debug { "firing on_close handler" }
72
- on_close.succeed
73
- end
94
+ logger.debug { "firing on_close handler" }
95
+ on_close.succeed
74
96
  @cnx = nil
75
97
  end
76
98
  else
@@ -83,12 +105,13 @@ module ZK
83
105
 
84
106
  # get data at path, optionally enabling a watch on the node
85
107
  #
86
- # @returns [Callback] returns a Callback which is an EM::Deferred (so you
108
+ # @return [Callback] returns a Callback which is an EM::Deferred (so you
87
109
  # can assign callbacks/errbacks) see Callback::Base for discussion
88
110
  #
89
111
  def get(path, opts={}, &block)
90
112
  Callback.new_get_cb(block) do |cb|
91
113
  cb.errback(&method(:connection_lost_hook))
114
+ cb.context = { :method => __method__, :path => path, :opts => opts }
92
115
  super(path, opts.merge(:callback => cb))
93
116
  end
94
117
  end
@@ -96,6 +119,7 @@ module ZK
96
119
  def create(path, data='', opts={}, &block)
97
120
  Callback.new_create_cb(block) do |cb|
98
121
  cb.errback(&method(:connection_lost_hook))
122
+ cb.context = { :method => __method__, :path => path, :data => data, :opts => opts }
99
123
  super(path, data, opts.merge(:callback => cb))
100
124
  end
101
125
  end
@@ -103,6 +127,7 @@ module ZK
103
127
  def set(path, data, opts={}, &block)
104
128
  Callback.new_set_cb(block) do |cb|
105
129
  cb.errback(&method(:connection_lost_hook))
130
+ cb.context = { :method => __method__, :path => path, :data => data, :opts => opts }
106
131
  super(path, data, opts.merge(:callback => cb))
107
132
  end
108
133
  end
@@ -114,6 +139,7 @@ module ZK
114
139
 
115
140
  Callback.__send__(meth, block) do |cb|
116
141
  cb.errback(&method(:connection_lost_hook))
142
+ cb.context = { :method => __method__, :path => path, :meth => meth, :opts => opts }
117
143
  super(path, opts.merge(:callback => cb))
118
144
  end
119
145
  end
@@ -125,6 +151,7 @@ module ZK
125
151
  def delete(path, opts={}, &block)
126
152
  Callback.new_delete_cb(block) do |cb|
127
153
  cb.errback(&method(:connection_lost_hook))
154
+ cb.context = { :method => __method__, :path => path, :opts => opts }
128
155
  super(path, opts.merge(:callback => cb))
129
156
  end
130
157
  end
@@ -132,6 +159,7 @@ module ZK
132
159
  def children(path, opts={}, &block)
133
160
  Callback.new_children_cb(block) do |cb|
134
161
  cb.errback(&method(:connection_lost_hook))
162
+ cb.context = { :method => __method__, :path => path, :opts => opts }
135
163
  super(path, opts.merge(:callback => cb))
136
164
  end
137
165
  end
@@ -139,6 +167,7 @@ module ZK
139
167
  def get_acl(path, opts={}, &block)
140
168
  Callback.new_get_acl_cb(block) do |cb|
141
169
  cb.errback(&method(:connection_lost_hook))
170
+ cb.context = { :method => __method__, :path => path, :opts => opts }
142
171
  super(path, opts.merge(:callback => cb))
143
172
  end
144
173
  end
@@ -146,25 +175,52 @@ module ZK
146
175
  def set_acl(path, acls, opts={}, &block)
147
176
  Callback.new_set_acl_cb(block) do |cb|
148
177
  cb.errback(&method(:connection_lost_hook))
178
+ cb.context = { :method => __method__, :path => path, :acls => acls, :opts => opts }
149
179
  super(path, acls, opts.merge(:callback => cb))
150
180
  end
151
181
  end
152
182
 
153
- # returns an EM::Synchrony compatible wrapper around this client
154
- def to_synchrony
155
- @synchrony_client ||= SynchronyClient.new(self)
183
+ # @return [Fixnum] The underlying connection's session_id
184
+ def session_id
185
+ return nil unless @cnx
186
+ @cnx.session_id
156
187
  end
157
188
 
158
- # returns self
159
- def to_async
160
- self
189
+ # @return [String] The underlying connection's session passwd (an opaque value)
190
+ def session_passwd
191
+ return nil unless @cnx
192
+ @cnx.session_passwd
161
193
  end
162
194
 
163
195
  protected
196
+ # @private
197
+ def register_default_event_handlers!
198
+ @event_handler.register_state_handler(Zookeeper::ZOO_EXPIRED_SESSION_STATE, &method(:handle_expired_session_state_event!))
199
+ @event_handler.register_state_handler(Zookeeper::ZOO_CONNECTED_STATE, &method(:handle_connected_state_event!))
200
+ @event_handler.register_state_handler(Zookeeper::ZOO_CONNECTING_STATE, &method(:handle_connecting_state_event!))
201
+ end
202
+
203
+ # @private
204
+ def handle_connected_state_event!(event)
205
+ EM.schedule { reset_connected_event.succeed(event) }
206
+ end
207
+
208
+ # @private
209
+ def handle_connecting_state_event!(event)
210
+ EM.schedule { reset_connecting_event.succeed(event) }
211
+ end
212
+
213
+ # @private
214
+ def handle_expired_session_state_event!(event)
215
+ exc = ZK::Exceptions::ConnectionLoss.new("Received EXPIRED_SESSION_STATE event: #{event.inspect}")
216
+ exc.set_backtrace(caller)
217
+ connection_lost_hook(exc)
218
+ end
219
+
220
+ # @private
164
221
  def connection_lost_hook(exc)
165
222
  if exc and exc.kind_of?(ZK::Exceptions::ConnectionLoss)
166
- dfr, @connection_lost_deferred = @connection_lost_deferred, Deferred::Default.new
167
- dfr.succeed(exc)
223
+ EM.schedule { reset_connection_lost_event.succeed(exc) }
168
224
  end
169
225
  end
170
226
  end
@@ -0,0 +1,229 @@
1
+ # Taken from EventMachine release candidate
2
+ module ZK
3
+ module ZKEventMachine
4
+ # A simple iterator for concurrent asynchronous work.
5
+ #
6
+ # Unlike ruby's built-in iterators, the end of the current iteration cycle is signaled manually,
7
+ # instead of happening automatically after the yielded block finishes executing. For example:
8
+ #
9
+ # (0..10).each{ |num| }
10
+ #
11
+ # becomes:
12
+ #
13
+ # EM::Iterator.new(0..10).each{ |num,iter| iter.next }
14
+ #
15
+ # This is especially useful when doing asynchronous work via reactor libraries and
16
+ # functions. For example, given a sync and async http api:
17
+ #
18
+ # response = sync_http_get(url); ...
19
+ # async_http_get(url){ |response| ... }
20
+ #
21
+ # a synchronous iterator such as:
22
+ #
23
+ # responses = urls.map{ |url| sync_http_get(url) }
24
+ # ...
25
+ # puts 'all done!'
26
+ #
27
+ # could be written as:
28
+ #
29
+ # EM::Iterator.new(urls).map(proc{ |url,iter|
30
+ # async_http_get(url){ |res|
31
+ # iter.return(res)
32
+ # }
33
+ # }, proc{ |responses|
34
+ # ...
35
+ # puts 'all done!'
36
+ # })
37
+ #
38
+ # Now, you can take advantage of the asynchronous api to issue requests in parallel. For example,
39
+ # to fetch 10 urls at a time, simply pass in a concurrency of 10:
40
+ #
41
+ # EM::Iterator.new(urls, 10).each do |url,iter|
42
+ # async_http_get(url){ iter.next }
43
+ # end
44
+ #
45
+ class Iterator
46
+ # Create a new parallel async iterator with specified concurrency.
47
+ #
48
+ # i = EM::Iterator.new(1..100, 10)
49
+ #
50
+ # will create an iterator over the range that processes 10 items at a time. Iteration
51
+ # is started via #each, #map or #inject
52
+ #
53
+ def initialize(list, concurrency = 1)
54
+ raise ArgumentError, 'argument must be an array' unless list.respond_to?(:to_a)
55
+ @list = list.to_a.dup
56
+ @concurrency = concurrency
57
+
58
+ @started = false
59
+ @ended = false
60
+ end
61
+
62
+ # Change the concurrency of this iterator. Workers will automatically be spawned or destroyed
63
+ # to accomodate the new concurrency level.
64
+ #
65
+ def concurrency=(val)
66
+ old = @concurrency
67
+ @concurrency = val
68
+
69
+ spawn_workers if val > old and @started and !@ended
70
+ end
71
+ attr_reader :concurrency
72
+
73
+ # Iterate over a set of items using the specified block or proc.
74
+ #
75
+ # EM::Iterator.new(1..100).each do |num, iter|
76
+ # puts num
77
+ # iter.next
78
+ # end
79
+ #
80
+ # An optional second proc is invoked after the iteration is complete.
81
+ #
82
+ # EM::Iterator.new(1..100).each(
83
+ # proc{ |num,iter| iter.next },
84
+ # proc{ puts 'all done' }
85
+ # )
86
+ #
87
+ def each(foreach=nil, after=nil, &blk)
88
+ raise ArgumentError, 'proc or block required for iteration' unless foreach ||= blk
89
+ raise RuntimeError, 'cannot iterate over an iterator more than once' if @started or @ended
90
+
91
+ @started = true
92
+ @pending = 0
93
+ @workers = 0
94
+
95
+ all_done = proc{
96
+ after.call if after and @ended and @pending == 0
97
+ }
98
+
99
+ @process_next = proc{
100
+ # p [:process_next, :pending=, @pending, :workers=, @workers, :ended=, @ended, :concurrency=, @concurrency, :list=, @list]
101
+ unless @ended or @workers > @concurrency
102
+ if @list.empty?
103
+ @ended = true
104
+ @workers -= 1
105
+ all_done.call
106
+ else
107
+ item = @list.shift
108
+ @pending += 1
109
+
110
+ is_done = false
111
+ on_done = proc{
112
+ raise RuntimeError, 'already completed this iteration' if is_done
113
+ is_done = true
114
+
115
+ @pending -= 1
116
+
117
+ if @ended
118
+ all_done.call
119
+ else
120
+ EM.next_tick(@process_next)
121
+ end
122
+ }
123
+ class << on_done
124
+ alias :next :call
125
+ end
126
+
127
+ foreach.call(item, on_done)
128
+ end
129
+ else
130
+ @workers -= 1
131
+ end
132
+ }
133
+
134
+ spawn_workers
135
+
136
+ self
137
+ end
138
+
139
+ # Collect the results of an asynchronous iteration into an array.
140
+ #
141
+ # EM::Iterator.new(%w[ pwd uptime uname date ], 2).map(proc{ |cmd,iter|
142
+ # EM.system(cmd){ |output,status|
143
+ # iter.return(output)
144
+ # }
145
+ # }, proc{ |results|
146
+ # p results
147
+ # })
148
+ #
149
+ def map(foreach, after)
150
+ index = 0
151
+
152
+ inject([], proc{ |results,item,iter|
153
+ i = index
154
+ index += 1
155
+
156
+ is_done = false
157
+ on_done = proc{ |res|
158
+ raise RuntimeError, 'already returned a value for this iteration' if is_done
159
+ is_done = true
160
+
161
+ results[i] = res
162
+ iter.return(results)
163
+ }
164
+ class << on_done
165
+ alias :return :call
166
+ def next
167
+ raise NoMethodError, 'must call #return on a map iterator'
168
+ end
169
+ end
170
+
171
+ foreach.call(item, on_done)
172
+ }, proc{ |results|
173
+ after.call(results)
174
+ })
175
+ end
176
+
177
+ # Inject the results of an asynchronous iteration onto a given object.
178
+ #
179
+ # EM::Iterator.new(%w[ pwd uptime uname date ], 2).inject({}, proc{ |hash,cmd,iter|
180
+ # EM.system(cmd){ |output,status|
181
+ # hash[cmd] = status.exitstatus == 0 ? output.strip : nil
182
+ # iter.return(hash)
183
+ # }
184
+ # }, proc{ |results|
185
+ # p results
186
+ # })
187
+ #
188
+ def inject(obj, foreach, after)
189
+ each(proc{ |item,iter|
190
+ is_done = false
191
+ on_done = proc{ |res|
192
+ raise RuntimeError, 'already returned a value for this iteration' if is_done
193
+ is_done = true
194
+
195
+ obj = res
196
+ iter.next
197
+ }
198
+ class << on_done
199
+ alias :return :call
200
+ def next
201
+ raise NoMethodError, 'must call #return on an inject iterator'
202
+ end
203
+ end
204
+
205
+ foreach.call(obj, item, on_done)
206
+ }, proc{
207
+ after.call(obj)
208
+ })
209
+ end
210
+
211
+ private
212
+
213
+ # Spawn workers to consume items from the iterator's enumerator based on the current concurrency level.
214
+ #
215
+ def spawn_workers
216
+ EM.next_tick(start_worker = proc{
217
+ if @workers < @concurrency and !@ended
218
+ # p [:spawning_worker, :workers=, @workers, :concurrency=, @concurrency, :ended=, @ended]
219
+ @workers += 1
220
+ @process_next.call
221
+ EM.next_tick(start_worker)
222
+ end
223
+ })
224
+ nil
225
+ end
226
+ end
227
+ end
228
+ end
229
+
@@ -3,7 +3,7 @@ module ZK
3
3
  module Unixisms
4
4
  def mkdir_p(paths, &block)
5
5
  dfr = Deferred::Default.new.tap do |my_dfr|
6
- EM::Iterator.new(Array(paths).flatten.compact, 1).map(
6
+ Iterator.new(Array(paths).flatten.compact, 1).map(
7
7
  lambda { |path,iter| # foreach
8
8
  d = _mkdir_p_dfr(path)
9
9
  d.callback { |p| iter.return(p) }
@@ -18,7 +18,7 @@ module ZK
18
18
 
19
19
  def rm_rf(paths, &blk)
20
20
  dfr = Deferred::Default.new.tap do |my_dfr|
21
- EM::Iterator.new(Array(paths).flatten.compact, 1).each(
21
+ Iterator.new(Array(paths).flatten.compact, 1).each(
22
22
  lambda { |path,iter| # foreach
23
23
  d = _rm_rf_dfr(path)
24
24
  d.callback { iter.next }
@@ -31,15 +31,18 @@ module ZK
31
31
  _handle_calling_convention(dfr, &blk)
32
32
  end
33
33
 
34
+ # @private
34
35
  def find(*paths, &block)
35
36
  raise NotImplementedError, "Coming soon"
36
37
  end
37
38
 
39
+ # @private
38
40
  def block_until_node_deleted(abs_node_path)
39
41
  raise NotImplementedError, "blocking does not make sense in EventMachine-land"
40
42
  end
41
43
 
42
44
  protected
45
+ # @private
43
46
  def _handle_calling_convention(dfr, &blk)
44
47
  return dfr unless blk
45
48
  dfr.callback { |*a| blk.call(nil, *a) }
@@ -47,6 +50,7 @@ module ZK
47
50
  dfr
48
51
  end
49
52
 
53
+ # @private
50
54
  def _rm_rf_dfr(path)
51
55
  Deferred::Default.new.tap do |my_dfr|
52
56
  delete(path) do |exc|
@@ -60,7 +64,7 @@ module ZK
60
64
  my_dfr.succeed
61
65
  when nil
62
66
  abspaths = chldrn.map { |n| [path, n].join('/') }
63
- EM::Iterator.new(abspaths).each(
67
+ Iterator.new(abspaths).each(
64
68
  lambda { |absp,iter|
65
69
  d = _rm_rf_dfr(absp)
66
70
  d.callback { |*|
@@ -85,6 +89,7 @@ module ZK
85
89
  end
86
90
  end
87
91
 
92
+ # @private
88
93
  def _mkdir_p_dfr(path)
89
94
  Deferred::Default.new.tap do |my_dfr|
90
95
  d = create(path, '')
@@ -1,5 +1,5 @@
1
1
  module ZK
2
2
  module ZKEventMachine
3
- VERSION = "0.2.0.beta.3"
3
+ VERSION = "0.9.0"
4
4
  end
5
5
  end