zk-eventmachine 0.2.0.beta.3 → 0.9.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/.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