em-synchrony 1.0.2 → 1.0.3

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/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