sinatra-synchrony 0.1.0.beta.2 → 0.1.0.beta.4
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/Gemfile +1 -1
- data/Gemfile.lock +3 -6
- data/README.markdown +31 -18
- data/lib/sinatra/synchrony.rb +11 -2
- data/lib/sinatra/synchrony/mock_session.rb +13 -0
- data/lib/sinatra/synchrony/tcpsocket.rb +6 -0
- data/spec/synchrony_spec.rb +3 -2
- metadata +6 -5
- data/lib/rack/test_synchrony.rb +0 -25
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
sinatra-synchrony (0.0.
|
5
|
-
async-rack (= 0.5.1)
|
4
|
+
sinatra-synchrony (0.1.0.beta.2)
|
6
5
|
em-http-request (= 0.3.0)
|
7
6
|
em-resolv-replace (= 1.1.1)
|
8
7
|
em-synchrony (= 0.2.0)
|
@@ -18,9 +17,7 @@ GEM
|
|
18
17
|
RubyInline (3.9.0)
|
19
18
|
ZenTest (~> 4.3)
|
20
19
|
ZenTest (4.5.0)
|
21
|
-
addressable (2.2.
|
22
|
-
async-rack (0.5.1)
|
23
|
-
rack (~> 1.1)
|
20
|
+
addressable (2.2.6)
|
24
21
|
diff-lcs (1.1.2)
|
25
22
|
em-http-request (0.3.0)
|
26
23
|
addressable (>= 2.0.0)
|
@@ -55,7 +52,7 @@ GEM
|
|
55
52
|
ruby_parser (>= 2.0.5)
|
56
53
|
sexp_processor (>= 3.0.5)
|
57
54
|
spruz (0.2.6)
|
58
|
-
tilt (1.3)
|
55
|
+
tilt (1.3.2)
|
59
56
|
wrong (0.5.0)
|
60
57
|
ParseTree (~> 3.0)
|
61
58
|
diff-lcs (~> 1.1.2)
|
data/README.markdown
CHANGED
@@ -43,14 +43,31 @@ If you are developing with a classic style app, just require the gem and it will
|
|
43
43
|
'Sinatra::Synchrony is loaded automatically in classic mode, nothing needed'
|
44
44
|
end
|
45
45
|
|
46
|
+
Net::HTTP / TCPSocket
|
47
|
+
---
|
48
|
+
If you're using anything based on TCPSocket (such as Net::HTTP, which is used by many things), you can replace the native Ruby TCPSocket with one that supports EventMachine and allows for concurrency:
|
49
|
+
|
50
|
+
Sinatra::Synchrony.overload_tcpsocket!
|
51
|
+
|
52
|
+
This will allow you to use things like [RestClient](https://github.com/archiloque/rest-client) without any changes:
|
53
|
+
|
54
|
+
RestClient.get 'http://google.com'
|
55
|
+
|
56
|
+
This is not perfect though - the TCPSocket overload doesn't currently support SSL and will throw an exception. This is more for when you have ruby libraries that use Net::HTTP and you want to try something. If you intend to do HTTP requests, I strongly recommend using [Faraday](https://github.com/technoweenie/faraday) instead, which has support for [EM-HTTP-Request](https://github.com/igrigorik/em-http-request).
|
57
|
+
|
58
|
+
Please encourage Ruby library developers to use (or at least support) Faraday instead of Net::HTTP. Aside from the inability to be concurrent natively, it's a pretty weird and crappy interface, which makes it harder to replace it with something better.
|
59
|
+
|
46
60
|
Tests
|
47
61
|
---
|
62
|
+
Add this to the top of your test file:
|
48
63
|
|
49
|
-
|
64
|
+
Sinatra::Synchrony.patch_tests!
|
65
|
+
|
66
|
+
Then just write your tests as usual, and all tests will be run within EventMachine. You must be in the __test__ environment so that Sinatra will not load Rack::FiberPool.
|
50
67
|
|
51
68
|
Benchmarks
|
52
69
|
---
|
53
|
-
|
70
|
+
Despite enabling synchronous programming without callbacks, there is no performance hit to your application! All the performance benefits you expect from Thin/Rainbows and EventMachine are still there:
|
54
71
|
|
55
72
|
class App < Sinatra::Base
|
56
73
|
register Sinatra::Synchrony
|
@@ -59,7 +76,7 @@ It's pretty fast!
|
|
59
76
|
end
|
60
77
|
end
|
61
78
|
|
62
|
-
|
79
|
+
Benchmarked with rackup -s thin:
|
63
80
|
|
64
81
|
$ ab -c 50 -n 2000 http://127.0.0.1:9292/
|
65
82
|
...
|
@@ -76,24 +93,22 @@ run with rackup -s thin:
|
|
76
93
|
|
77
94
|
Let's try a simple blocking IO example to prove it works. 100 hits to google.com:
|
78
95
|
|
96
|
+
require 'sinatra'
|
97
|
+
require 'sinatra/synchrony'
|
79
98
|
require 'rest-client'
|
80
|
-
|
81
|
-
|
82
|
-
register Sinatra::Synchrony
|
83
|
-
get '/' do
|
84
|
-
# Using EventMachine::HttpRequest
|
85
|
-
# EM::Synchrony.sync(EventMachine::HttpRequest.new('http://google.com').get).response
|
99
|
+
require 'faraday'
|
100
|
+
Faraday.default_adapter = :em_synchrony
|
86
101
|
|
87
|
-
|
88
|
-
|
89
|
-
end
|
102
|
+
get '/' do
|
103
|
+
Faraday.get 'http://google.com'
|
90
104
|
end
|
91
105
|
|
106
|
+
|
92
107
|
$ ab -c 100 -n 100 http://127.0.0.1:9292/
|
93
108
|
...
|
94
|
-
Time taken for tests:
|
95
|
-
|
96
|
-
For a perspective, this operation takes __33 seconds__ without this extension.
|
109
|
+
Time taken for tests: 0.256 seconds
|
110
|
+
|
111
|
+
For a perspective, this operation takes __33 seconds__ without this extension.
|
97
112
|
|
98
113
|
Geoloqi
|
99
114
|
---
|
@@ -101,9 +116,7 @@ This gem was designed to help us develop faster games and internal applications
|
|
101
116
|
|
102
117
|
TODO / Thoughts
|
103
118
|
---
|
104
|
-
*
|
105
|
-
* Provide better method for patching Rack::Test that's less fragile to version changes. This is a big priority and I intend to improve this. Pull requests here welcome!
|
106
|
-
* Research way to run tests with Rack::FiberPool enabled.
|
119
|
+
* We are using this in production without any problems, and it's very stable for us. But you should test before deploying anything with it.
|
107
120
|
* There is work underway to make this a Rack middleware, and integrate that middleware with this plugin. That way, many other frameworks can take advantage of this. There is also work exploratory work to provide support for non-EventMachine Reactor pattern implementations with this approach, but it's beyond the scope of this extension.
|
108
121
|
|
109
122
|
Author
|
data/lib/sinatra/synchrony.rb
CHANGED
@@ -4,7 +4,6 @@ require 'eventmachine'
|
|
4
4
|
require 'em-http-request'
|
5
5
|
require 'em-synchrony'
|
6
6
|
require 'em-resolv-replace'
|
7
|
-
require 'net/http'
|
8
7
|
|
9
8
|
module Sinatra
|
10
9
|
module Synchrony
|
@@ -12,6 +11,16 @@ module Sinatra
|
|
12
11
|
builder.use Rack::FiberPool unless test?
|
13
12
|
super
|
14
13
|
end
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def patch_tests!
|
17
|
+
require 'sinatra/synchrony/mock_session'
|
18
|
+
end
|
19
|
+
|
20
|
+
def overload_tcpsocket!
|
21
|
+
require 'sinatra/synchrony/tcpsocket'
|
22
|
+
end
|
23
|
+
end
|
15
24
|
end
|
16
25
|
register Synchrony
|
17
|
-
end
|
26
|
+
end
|
data/spec/synchrony_spec.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
ENV['RACK_ENV'] = 'test'
|
2
2
|
require File.join(File.join(File.expand_path(File.dirname(__FILE__))), '..', 'lib', 'sinatra', 'synchrony')
|
3
|
-
require
|
3
|
+
require 'rack/test'
|
4
4
|
require 'minitest/autorun'
|
5
5
|
require 'wrong/adapters/minitest'
|
6
|
+
Sinatra::Synchrony.patch_tests!
|
6
7
|
Wrong.config.alias_assert :expect
|
7
8
|
|
8
9
|
def mock_app(base=Sinatra::Base, &block)
|
@@ -40,4 +41,4 @@ describe 'A mock app' do
|
|
40
41
|
expect { last_response.ok? }
|
41
42
|
expect { last_response.headers['Set-Cookie'] }
|
42
43
|
end
|
43
|
-
end
|
44
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sinatra-synchrony
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 62196411
|
5
5
|
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
9
|
- 0
|
10
10
|
- beta
|
11
|
-
-
|
12
|
-
version: 0.1.0.beta.
|
11
|
+
- 4
|
12
|
+
version: 0.1.0.beta.4
|
13
13
|
platform: ruby
|
14
14
|
authors:
|
15
15
|
- Kyle Drake
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2011-
|
20
|
+
date: 2011-08-01 00:00:00 Z
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
23
23
|
name: sinatra
|
@@ -168,8 +168,9 @@ extensions: []
|
|
168
168
|
extra_rdoc_files: []
|
169
169
|
|
170
170
|
files:
|
171
|
+
- lib/sinatra/synchrony/mock_session.rb
|
172
|
+
- lib/sinatra/synchrony/tcpsocket.rb
|
171
173
|
- lib/sinatra/synchrony.rb
|
172
|
-
- lib/rack/test_synchrony.rb
|
173
174
|
- spec/synchrony_spec.rb
|
174
175
|
- Gemfile
|
175
176
|
- Gemfile.lock
|
data/lib/rack/test_synchrony.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'rack/test'
|
2
|
-
# Monkeypatch to provide EM within tests.
|
3
|
-
# If you have a better approach, please send a pull request!
|
4
|
-
|
5
|
-
module Rack
|
6
|
-
class MockSession
|
7
|
-
def request(uri, env)
|
8
|
-
env["HTTP_COOKIE"] ||= cookie_jar.for(uri)
|
9
|
-
@last_request = Rack::Request.new(env)
|
10
|
-
EM.synchrony do
|
11
|
-
status, headers, body = @app.call(@last_request.env)
|
12
|
-
@last_response = MockResponse.new(status, headers, body, env["rack.errors"].flush)
|
13
|
-
body.close if body.respond_to?(:close)
|
14
|
-
cookie_jar.merge(last_response.headers["Set-Cookie"], uri)
|
15
|
-
@after_request.each { |hook| hook.call }
|
16
|
-
if @last_response.respond_to?(:finish)
|
17
|
-
@last_response.finish
|
18
|
-
else
|
19
|
-
@last_response
|
20
|
-
end
|
21
|
-
EM.stop
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|