em-synchrony 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -8,7 +8,7 @@ Collection of convenience classes and primitives to help untangle evented code,
8
8
  * Fiber aware Multi-request interface for any callback enabled clients
9
9
  * Fiber aware TCPSocket replacement, powered by EventMachine
10
10
  * Fiber aware Thread, Mutex, ConditionVariable clases
11
- * Fiber aware sleep
11
+ * Fiber aware sleep, defer, system
12
12
 
13
13
  Supported clients:
14
14
 
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "em-synchrony"
6
- s.version = "1.0.2"
6
+ s.version = "1.0.3"
7
7
  s.platform = Gem::Platform::RUBY
8
8
  s.authors = ["Ilya Grigorik"]
9
9
  s.email = ["ilya@igvita.com"]
@@ -18,14 +18,29 @@ require "em-synchrony/iterator" if EventMachine::VERSION > '0.12.10'
18
18
 
19
19
  module EventMachine
20
20
 
21
- # A convenience method for wrapping EM.run body within
21
+ # A convenience method for wrapping a given block within
22
22
  # a Ruby Fiber such that async operations can be transparently
23
23
  # paused and resumed based on IO scheduling.
24
- def self.synchrony(blk=nil, tail=nil, &block)
25
- blk ||= block
26
- context = Proc.new { Fiber.new { blk.call }.resume }
24
+ # It detects whether EM is running or not.
25
+ def self.synchrony(blk=nil, tail=nil)
26
+ # EM already running.
27
+ if reactor_running?
28
+ if block_given?
29
+ Fiber.new { yield }.resume
30
+ else
31
+ Fiber.new { blk.call }.resume
32
+ end
33
+ tail && add_shutdown_hook(tail)
34
+
35
+ # EM not running.
36
+ else
37
+ if block_given?
38
+ run(nil, tail) { Fiber.new { yield }.resume }
39
+ else
40
+ run(Proc.new { Fiber.new { blk.call }.resume }, tail)
41
+ end
27
42
 
28
- self.run(context, tail)
43
+ end
29
44
  end
30
45
 
31
46
  module Synchrony
@@ -98,6 +113,22 @@ module EventMachine
98
113
  def self.next_tick(&blk)
99
114
  EM.next_tick { Fiber.new { blk.call }.resume }
100
115
  end
116
+
117
+ # Fiber-aware EM.defer
118
+ #
119
+ def self.defer op = nil, &blk
120
+ fiber = Fiber.current
121
+ EM.defer(op || blk, lambda{ |result| fiber.resume(result) })
122
+ Fiber.yield
123
+ end
124
+
125
+ # Fiber-aware EM.system
126
+ #
127
+ def self.system cmd, *args
128
+ fiber = Fiber.current
129
+ EM.system(cmd, *args){ |out, status| fiber.resume( [out, status] ) }
130
+ Fiber.yield
131
+ end
101
132
 
102
133
  # Routes to EM::Synchrony::Keyboard
103
134
  #
@@ -116,9 +116,21 @@ module EventMachine
116
116
  class Exchange < ::AMQP::Exchange
117
117
  def initialize(channel, type, name, opts = {}, &block)
118
118
  f = Fiber.current
119
- super(channel, type, name, opts, &EM::Synchrony::AMQP.sync_cb(f))
120
- exchange, declare_ok = Fiber.yield
121
- raise Error.new unless declare_ok.is_a?(::AMQ::Protocol::Exchange::DeclareOk)
119
+
120
+ # AMQP Exchange constructor handles certain special exchanges differently.
121
+ # The callback passed in isn't called when the response comes back
122
+ # but is called immediately on the original calling fiber. That means that
123
+ # when the sync_cb callback yields the fiber when called, it will hang and never
124
+ # be resumed. So handle these exchanges without yielding
125
+ if name == "amq.#{type}" or name.empty? or opts[:no_declare]
126
+ exchange = nil
127
+ super(channel, type, name, opts) { |ex| exchange = ex }
128
+ else
129
+ super(channel, type, name, opts, &EM::Synchrony::AMQP.sync_cb(f))
130
+ exchange, declare_ok = Fiber.yield
131
+ raise Error.new(declare_ok.to_s) unless declare_ok.is_a?(::AMQ::Protocol::Exchange::DeclareOk)
132
+ end
133
+
122
134
  exchange
123
135
  end
124
136
 
@@ -143,9 +155,9 @@ module EventMachine
143
155
  end
144
156
 
145
157
  alias :asubscribe :subscribe
146
- def subscribe &block
158
+ def subscribe(opts = {}, &block)
147
159
  Fiber.new do
148
- asubscribe(&EM::Synchrony::AMQP.sync_cb(Fiber.current))
160
+ asubscribe(opts, &EM::Synchrony::AMQP.sync_cb(Fiber.current))
149
161
  loop { block.call(Fiber.yield) }
150
162
  end.resume
151
163
  end
@@ -6,7 +6,7 @@ end
6
6
 
7
7
  module EventMachine
8
8
  module HTTPMethods
9
- %w[get head post delete put].each do |type|
9
+ %w[get head post delete put patch options].each do |type|
10
10
  class_eval %[
11
11
  alias :a#{type} :#{type}
12
12
  def #{type}(options = {}, &blk)
@@ -16,7 +16,7 @@ module EventMachine
16
16
  if conn.error.nil?
17
17
  conn.callback { f.resume(conn) }
18
18
  conn.errback { f.resume(conn) }
19
-
19
+
20
20
  Fiber.yield
21
21
  else
22
22
  conn
@@ -1,5 +1,5 @@
1
1
  begin
2
- require "mongo/connection"
2
+ require "mongo"
3
3
  rescue LoadError => error
4
4
  raise "Missing EM-Synchrony dependency: gem install mongo"
5
5
  end
@@ -83,7 +83,7 @@ describe EM::Synchrony::AMQP do
83
83
  nb_q1, nb_q2 = 0, 0
84
84
  stop_cb = proc { EM.stop if nb_q1 + nb_q2 == 2 * nb_msg }
85
85
 
86
- q1.subscribe do |meta, msg|
86
+ q1.subscribe(:ack => false) do |meta, msg|
87
87
  msg.should match(/^Bonjour [0-9]+/)
88
88
  nb_q1 += 1
89
89
  stop_cb.call
@@ -0,0 +1,40 @@
1
+ require "spec/helper/all"
2
+
3
+ describe EventMachine::Synchrony do
4
+
5
+ it "defer: simple" do
6
+ EM.synchrony do
7
+ x = 1
8
+
9
+ result = EM::Synchrony.defer do
10
+ x = 2
11
+ sleep 0.1
12
+ 3
13
+ end
14
+
15
+ result.should == 3
16
+ x.should == 2
17
+
18
+ EM.stop
19
+ end
20
+ end
21
+
22
+ it "defer: with lambda" do
23
+ EM.synchrony do
24
+
25
+ x = 1
26
+
27
+ op = lambda do
28
+ sleep 0.1
29
+ x += 1
30
+ 3
31
+ end
32
+
33
+ EM::Synchrony.defer(op).should == 3
34
+ x.should == 2
35
+
36
+ EM.stop
37
+ end
38
+ end
39
+
40
+ end
@@ -28,9 +28,11 @@ describe EventMachine::HttpRequest do
28
28
  order.push :head if EventMachine::HttpRequest.new(URL).head
29
29
  order.push :post if EventMachine::HttpRequest.new(URL).delete
30
30
  order.push :put if EventMachine::HttpRequest.new(URL).put
31
+ order.push :options if EventMachine::HttpRequest.new(URL).options
32
+ order.push :patch if EventMachine::HttpRequest.new(URL).patch
31
33
 
32
34
  (now - start.to_f).should be_within(DELAY * order.size * 0.15).of(DELAY * order.size)
33
- order.should == [:get, :post, :head, :post, :put]
35
+ order.should == [:get, :post, :head, :post, :put, :options, :patch]
34
36
 
35
37
  s.stop
36
38
  EventMachine.stop
@@ -49,10 +51,12 @@ describe EventMachine::HttpRequest do
49
51
  multi.add :c, EventMachine::HttpRequest.new(URL).ahead
50
52
  multi.add :d, EventMachine::HttpRequest.new(URL).adelete
51
53
  multi.add :e, EventMachine::HttpRequest.new(URL).aput
54
+ multi.add :f, EventMachine::HttpRequest.new(URL).aoptions
55
+ multi.add :g, EventMachine::HttpRequest.new(URL).apatch
52
56
  res = multi.perform
53
57
 
54
58
  (now - start.to_f).should be_within(DELAY * 0.15).of(DELAY)
55
- res.responses[:callback].size.should == 5
59
+ res.responses[:callback].size.should == 7
56
60
  res.responses[:errback].size.should == 0
57
61
 
58
62
  s.stop
@@ -0,0 +1,17 @@
1
+ require "spec/helper/all"
2
+
3
+ describe EventMachine::Synchrony do
4
+
5
+ it "system: simple" do
6
+ EM.synchrony do
7
+ out, status = EM::Synchrony.system("echo 'some'")
8
+
9
+ status.should == 0
10
+ out.should == "some\n"
11
+
12
+ EM.stop
13
+ end
14
+ end
15
+
16
+
17
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: em-synchrony
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-18 00:00:00.000000000 Z
12
+ date: 2013-01-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine
@@ -74,6 +74,7 @@ files:
74
74
  - spec/amqp_spec.rb
75
75
  - spec/beanstalk_spec.rb
76
76
  - spec/connection_pool_spec.rb
77
+ - spec/defer_spec.rb
77
78
  - spec/em-mongo_spec.rb
78
79
  - spec/fiber_iterator_spec.rb
79
80
  - spec/helper/all.rb
@@ -91,6 +92,7 @@ files:
91
92
  - spec/redis_spec.rb
92
93
  - spec/remcached_spec.rb
93
94
  - spec/synchrony_spec.rb
95
+ - spec/system_spec.rb
94
96
  - spec/tcpsocket_spec.rb
95
97
  - spec/thread_spec.rb
96
98
  - spec/timer_spec.rb
@@ -123,6 +125,7 @@ test_files:
123
125
  - spec/amqp_spec.rb
124
126
  - spec/beanstalk_spec.rb
125
127
  - spec/connection_pool_spec.rb
128
+ - spec/defer_spec.rb
126
129
  - spec/em-mongo_spec.rb
127
130
  - spec/fiber_iterator_spec.rb
128
131
  - spec/helper/all.rb
@@ -140,6 +143,7 @@ test_files:
140
143
  - spec/redis_spec.rb
141
144
  - spec/remcached_spec.rb
142
145
  - spec/synchrony_spec.rb
146
+ - spec/system_spec.rb
143
147
  - spec/tcpsocket_spec.rb
144
148
  - spec/thread_spec.rb
145
149
  - spec/timer_spec.rb