zk-eventmachine 0.2.0.beta.1 → 0.2.0.beta.2

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
1
+ rvm 1.9.2@zk-em --create
@@ -29,6 +29,9 @@ module ZK
29
29
  def connect(&blk)
30
30
  # XXX: maybe move this into initialize, need to figure out how to schedule it properly
31
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
32
35
  @cnx.on_attached(&blk)
33
36
  end
34
37
 
@@ -63,8 +66,11 @@ module ZK
63
66
 
64
67
  logger.debug { "#{self.class.name}: calling @cnx.close" }
65
68
  @cnx.close do
66
- logger.debug { "firing on_close handler" }
67
- on_close.succeed
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
68
74
  @cnx = nil
69
75
  end
70
76
  else
@@ -144,6 +150,16 @@ module ZK
144
150
  end
145
151
  end
146
152
 
153
+ # returns an EM::Synchrony compatible wrapper around this client
154
+ def to_synchrony
155
+ @synchrony_client ||= SynchronyClient.new(self)
156
+ end
157
+
158
+ # returns self
159
+ def to_async
160
+ self
161
+ end
162
+
147
163
  protected
148
164
  def connection_lost_hook(exc)
149
165
  if exc and exc.kind_of?(ZK::Exceptions::ConnectionLoss)
@@ -58,7 +58,7 @@ module ZK
58
58
  @event_handler = SynchronyEventHandlerWrapper.new(@client.event_handler)
59
59
  end
60
60
 
61
- %w[connect close close! get set create stat delete children get_acl set_acl mkdir_p rm_rf].each do |meth|
61
+ %w[connect get set create stat delete children get_acl set_acl mkdir_p rm_rf].each do |meth|
62
62
  class_eval(<<-EOMETH, __FILE__, __LINE__ + 1)
63
63
  def #{meth}(*args,&blk)
64
64
  sync!(@client.#{meth}(*args, &blk))
@@ -66,6 +66,18 @@ module ZK
66
66
  EOMETH
67
67
  end
68
68
 
69
+ # it is *crucially* important that close and close! be wrapped in a fiber.
70
+ # it's possible under very odd corner cases with the 1.9.3 GC to cause a
71
+ # '[BUG] cfp consistency error - send'
72
+ #
73
+ %w[close close!].each do |meth|
74
+ class_eval(<<-EOMETH, __FILE__, __LINE__ + 1)
75
+ def #{meth}(*args,&blk)
76
+ Fiber.new { sync!(@client.#{meth}(*args, &blk)) }.resume
77
+ end
78
+ EOMETH
79
+ end
80
+
69
81
  # @deprecated for backwards compatibility only
70
82
  def watcher
71
83
  event_handler
@@ -75,6 +87,16 @@ module ZK
75
87
  stat(path, opts={}).exists?
76
88
  end
77
89
 
90
+ # returns self
91
+ def to_synchrony
92
+ self
93
+ end
94
+
95
+ # returns the wrapped async client
96
+ def to_async
97
+ @client
98
+ end
99
+
78
100
  protected
79
101
  # a modification of EM::Synchrony.sync to handle multiple callback arguments properly
80
102
  def sync(df)
@@ -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
- Iterator.new(Array(paths).flatten.compact, 1).map(
6
+ EM::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
- Iterator.new(Array(paths).flatten.compact, 1).each(
21
+ EM::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 }
@@ -60,7 +60,7 @@ module ZK
60
60
  my_dfr.succeed
61
61
  when nil
62
62
  abspaths = chldrn.map { |n| [path, n].join('/') }
63
- Iterator.new(abspaths).each(
63
+ EM::Iterator.new(abspaths).each(
64
64
  lambda { |absp,iter|
65
65
  d = _rm_rf_dfr(absp)
66
66
  d.callback { |*|
@@ -1,5 +1,5 @@
1
1
  module ZK
2
2
  module ZKEventMachine
3
- VERSION = "0.2.0.beta.1"
3
+ VERSION = "0.2.0.beta.2"
4
4
  end
5
5
  end
@@ -6,7 +6,6 @@ require 'zookeeper/em_client'
6
6
 
7
7
  require 'zk'
8
8
 
9
-
10
9
  module ZK
11
10
  module ZKEventMachine
12
11
  end
@@ -15,7 +14,6 @@ end
15
14
 
16
15
  $LOAD_PATH.unshift(File.expand_path('../..', __FILE__)).uniq!
17
16
 
18
- require 'z_k/z_k_event_machine/iterator'
19
17
  require 'z_k/z_k_event_machine/deferred'
20
18
  require 'z_k/z_k_event_machine/callback'
21
19
  require 'z_k/z_k_event_machine/event_handler_e_m'
@@ -29,7 +29,8 @@ module ZK
29
29
  @base_path = '/zk-em-testing'
30
30
  @zk.rm_rf(@base_path)
31
31
  @zk.mkdir_p(@base_path)
32
- @zksync = ZK::ZKEventMachine::SynchronyClient.new('localhost:2181')
32
+ # $stderr.puts "zk obj_id: %x" % [@zk.object_id]
33
+ @zksync = ZK::ZKEventMachine::SynchronyClient.new('localhost:2181', :zkc_log_level => 4)
33
34
  end
34
35
 
35
36
  after do
@@ -324,6 +325,8 @@ module ZK
324
325
  @zksync.event_handler.register(@new_path) do |event|
325
326
  logger.debug { "got event #{event}" }
326
327
 
328
+ # without close! wrapping itself in Fiber.new, this causes a
329
+ # '[BUG] cfp consistency error - send' under 1.9.3
327
330
  done { @zksync.close! }
328
331
  end
329
332
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zk-eventmachine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0.beta.1
4
+ version: 0.2.0.beta.2
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-01 00:00:00.000000000Z
12
+ date: 2011-11-15 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: zk
16
- requirement: &2169005720 !ruby/object:Gem::Requirement
16
+ requirement: &2156053200 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 0.8.5
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2169005720
24
+ version_requirements: *2156053200
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: slyphon-zookeeper
27
- requirement: &2169005220 !ruby/object:Gem::Requirement
27
+ requirement: &2156052080 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.2.4
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2169005220
35
+ version_requirements: *2156052080
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: eventmachine
38
- requirement: &2169004760 !ruby/object:Gem::Requirement
38
+ requirement: &2156051200 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.0.0.beta.3
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *2169004760
46
+ version_requirements: *2156051200
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: em-synchrony
49
- requirement: &2169004260 !ruby/object:Gem::Requirement
49
+ requirement: &2156050280 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 1.0.0
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *2169004260
57
+ version_requirements: *2156050280
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rspec
60
- requirement: &2169003800 !ruby/object:Gem::Requirement
60
+ requirement: &2156049400 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 2.5.0
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *2169003800
68
+ version_requirements: *2156049400
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: yard
71
- requirement: &2169003260 !ruby/object:Gem::Requirement
71
+ requirement: &2156048620 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: 0.7.0
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *2169003260
79
+ version_requirements: *2156048620
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: autotest
82
- requirement: &2169002720 !ruby/object:Gem::Requirement
82
+ requirement: &2156047400 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: 4.4.0
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *2169002720
90
+ version_requirements: *2156047400
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: flexmock
93
- requirement: &2169002220 !ruby/object:Gem::Requirement
93
+ requirement: &2156046380 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ~>
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: 0.8.10
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *2169002220
101
+ version_requirements: *2156046380
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: evented-spec
104
- requirement: &2169001680 !ruby/object:Gem::Requirement
104
+ requirement: &2156045160 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ~>
@@ -109,7 +109,7 @@ dependencies:
109
109
  version: 0.4.1
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *2169001680
112
+ version_requirements: *2156045160
113
113
  description: ''
114
114
  email:
115
115
  - slyphon@hp.com
@@ -131,7 +131,6 @@ files:
131
131
  - lib/z_k/z_k_event_machine/client.rb
132
132
  - lib/z_k/z_k_event_machine/deferred.rb
133
133
  - lib/z_k/z_k_event_machine/event_handler_e_m.rb
134
- - lib/z_k/z_k_event_machine/iterator.rb
135
134
  - lib/z_k/z_k_event_machine/synchrony_client.rb
136
135
  - lib/z_k/z_k_event_machine/unixisms.rb
137
136
  - lib/z_k/z_k_event_machine/version.rb
@@ -1,229 +0,0 @@
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
-