grape-async 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +6 -21
- data/Guardfile +1 -1
- data/README.md +14 -0
- data/examples/config.ru +2 -2
- data/grape-async.gemspec +2 -2
- data/lib/grape-async.rb +2 -2
- data/lib/grape-async/async.rb +73 -0
- data/lib/grape-async/{api.rb → extension.rb} +5 -3
- data/spec/lib/grape-async/{middleware/async_spec.rb → async_spec.rb} +47 -28
- data/spec/support/endpoint_faker.rb +25 -20
- metadata +9 -9
- data/lib/grape-async/middleware/async.rb +0 -71
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7818cb5a44ad63386d861fd483b728ffd55b746c
|
4
|
+
data.tar.gz: f9f8b85b67ef81d34a61a4d3bdb69a8f808123f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b40b12de2ddf6a8254b0d5a0982f02ba7be4e3e27e63910e7e7befc5902dbfbd8315ca0189986201d653fce8f818446597ea0de3597d18e6ae325a2823c1847
|
7
|
+
data.tar.gz: 2b5b48fb30d35bf643a100691eed443c67b98d18626f86dbd56e2601c51b0c20052b8719ab395a9094798bc0204eafb8b89ee732cb3259003c906c53f1c0ec2d
|
data/Gemfile.lock
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
grape-async (0.1.
|
5
|
-
activesupport
|
6
|
-
eventmachine
|
7
|
-
grape
|
4
|
+
grape-async (0.1.2)
|
5
|
+
activesupport (~> 4.2)
|
6
|
+
eventmachine (~> 1.0)
|
7
|
+
grape (~> 0.14)
|
8
8
|
|
9
9
|
GEM
|
10
10
|
remote: https://rubygems.org/
|
@@ -20,12 +20,6 @@ GEM
|
|
20
20
|
ice_nine (~> 0.11.0)
|
21
21
|
thread_safe (~> 0.3, >= 0.3.1)
|
22
22
|
builder (3.2.2)
|
23
|
-
capybara (2.5.0)
|
24
|
-
mime-types (>= 1.16)
|
25
|
-
nokogiri (>= 1.3.3)
|
26
|
-
rack (>= 1.0.0)
|
27
|
-
rack-test (>= 0.5.4)
|
28
|
-
xpath (~> 2.0)
|
29
23
|
coderay (1.1.0)
|
30
24
|
coercible (1.0.0)
|
31
25
|
descendants_tracker (~> 0.0.1)
|
@@ -70,16 +64,10 @@ GEM
|
|
70
64
|
rb-inotify (>= 0.9)
|
71
65
|
lumberjack (1.0.9)
|
72
66
|
method_source (0.8.2)
|
73
|
-
mime-types (3.0)
|
74
|
-
mime-types-data (~> 3.2015)
|
75
|
-
mime-types-data (3.2015.1120)
|
76
|
-
mini_portile2 (2.0.0)
|
77
67
|
minitest (5.8.3)
|
78
68
|
multi_json (1.11.2)
|
79
69
|
multi_xml (0.5.5)
|
80
70
|
nenv (0.2.0)
|
81
|
-
nokogiri (1.6.7.1)
|
82
|
-
mini_portile2 (~> 2.0.0.rc2)
|
83
71
|
notiffany (0.0.8)
|
84
72
|
nenv (~> 0.1)
|
85
73
|
shellany (~> 0.0)
|
@@ -127,21 +115,18 @@ GEM
|
|
127
115
|
coercible (~> 1.0)
|
128
116
|
descendants_tracker (~> 0.0, >= 0.0.3)
|
129
117
|
equalizer (~> 0.0, >= 0.0.9)
|
130
|
-
xpath (2.0.0)
|
131
|
-
nokogiri (~> 1.3)
|
132
118
|
|
133
119
|
PLATFORMS
|
134
120
|
ruby
|
135
121
|
|
136
122
|
DEPENDENCIES
|
137
|
-
bundler
|
138
|
-
capybara
|
123
|
+
bundler (~> 1.0)
|
139
124
|
grape-async!
|
140
125
|
guard
|
141
126
|
guard-rspec
|
142
127
|
pry
|
143
128
|
puma
|
144
|
-
rack-test
|
129
|
+
rack-test (~> 0.5)
|
145
130
|
rake
|
146
131
|
rspec
|
147
132
|
thin
|
data/Guardfile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# A sample Guardfile
|
2
2
|
# More info at https://github.com/guard/guard#readme
|
3
3
|
|
4
|
-
guard :rspec, cmd: 'bundle exec rspec', after_all_pass: false do
|
4
|
+
guard :rspec, cmd: 'bundle exec rspec', after_all_pass: false, failed_mode: :focus do
|
5
5
|
watch(%r{^spec/.+_spec\.rb$})
|
6
6
|
watch(%r{^spec/support/.+$}) { "spec" }
|
7
7
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
data/README.md
CHANGED
@@ -30,6 +30,20 @@ end
|
|
30
30
|
The `async` directive accepts either `:em` for EventMachine based async or `:threaded` for thread based async.
|
31
31
|
The default is `:threaded`.
|
32
32
|
|
33
|
+
## Examples
|
34
|
+
|
35
|
+
To run the provided example with Thin:
|
36
|
+
|
37
|
+
```shell
|
38
|
+
bundle exec thin start -R examples/config.ru
|
39
|
+
```
|
40
|
+
|
41
|
+
or with Puma
|
42
|
+
|
43
|
+
```shell
|
44
|
+
bundle exec puma examples/config.ru -t 8:32 -w 3 -b tcp://0.0.0.0:3000
|
45
|
+
```
|
46
|
+
|
33
47
|
## Contributing
|
34
48
|
|
35
49
|
1. Fork it ( https://github.com/stuart/grape-async/fork )
|
data/examples/config.ru
CHANGED
data/grape-async.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "grape-async"
|
7
|
-
spec.version = '0.1.
|
7
|
+
spec.version = '0.1.3'
|
8
8
|
spec.platform = Gem::Platform::RUBY
|
9
9
|
spec.authors = ["Lachlan Laycock"]
|
10
10
|
spec.email = ["l.laycock@stuart.com"]
|
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_dependency "eventmachine", '~> 1.0'
|
23
23
|
spec.add_dependency "activesupport", '~> 4.2'
|
24
24
|
|
25
|
-
spec.add_development_dependency 'bundler', '~>
|
25
|
+
spec.add_development_dependency 'bundler', '~> 1.0'
|
26
26
|
spec.add_development_dependency 'rake', '~> 10.0'
|
27
27
|
spec.add_development_dependency 'rack-test', '~> 0.5'
|
28
28
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
data/lib/grape-async.rb
CHANGED
@@ -0,0 +1,73 @@
|
|
1
|
+
module Grape
|
2
|
+
class Async < Grape::Middleware::Base
|
3
|
+
|
4
|
+
def call!(env)
|
5
|
+
@env = env
|
6
|
+
if endpoint.async_route? && !async_io.nil?
|
7
|
+
if endpoint.async_route?(:em)
|
8
|
+
proc = lambda {
|
9
|
+
EM.next_tick do
|
10
|
+
super
|
11
|
+
endpoint.deferred_resp.callback do
|
12
|
+
resp = endpoint.file || [endpoint.body]
|
13
|
+
async_call [endpoint.status, endpoint.header, resp]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
}
|
17
|
+
if !EM.reactor_running?
|
18
|
+
EM.run do
|
19
|
+
proc.call
|
20
|
+
end
|
21
|
+
else
|
22
|
+
proc.call
|
23
|
+
end
|
24
|
+
|
25
|
+
else
|
26
|
+
Thread.new do
|
27
|
+
result = super
|
28
|
+
async_call result
|
29
|
+
yield
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
[-1, {}, []] # Return async response
|
34
|
+
|
35
|
+
else
|
36
|
+
super
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def async_call(result)
|
42
|
+
if @env['async.callback']
|
43
|
+
async_io.call result
|
44
|
+
elsif @env['rack.hijack']
|
45
|
+
status, headers, body = result
|
46
|
+
begin
|
47
|
+
async_io.write("HTTP/1.1 #{status}\r\n")
|
48
|
+
headers.each do |key, value|
|
49
|
+
async_io.write("#{key}: #{value}\r\n")
|
50
|
+
end
|
51
|
+
async_io.write("Connection: close\r\n")
|
52
|
+
async_io.write("\r\n")
|
53
|
+
body.each do |data|
|
54
|
+
async_io.write(data)
|
55
|
+
end
|
56
|
+
ensure
|
57
|
+
async_io.close
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def async_io
|
63
|
+
@async_io ||= @env['async.callback'] || begin
|
64
|
+
@env.key?('rack.hijack') ? @env['rack.hijack'].call : nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def endpoint
|
69
|
+
@env[Grape::Env::API_ENDPOINT]
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -3,18 +3,26 @@ require 'eventmachine'
|
|
3
3
|
require 'thin'
|
4
4
|
require 'puma'
|
5
5
|
|
6
|
-
describe Grape::
|
6
|
+
describe Grape::Async do
|
7
7
|
|
8
8
|
def setup_async_obj!
|
9
9
|
async_obj = double(:async_obj)
|
10
10
|
allow(async_obj).to receive(:call)
|
11
|
-
allow_any_instance_of(Grape::
|
11
|
+
allow_any_instance_of(Grape::Async).to receive(:async_io) {
|
12
12
|
async_obj
|
13
13
|
}
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
def kill_server
|
17
|
+
@server.kill if @server.is_a?(Thread) and @server.alive?
|
18
|
+
end
|
19
|
+
|
20
|
+
def port
|
21
|
+
3333
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:host) { 'localhost' }
|
25
|
+
let(:delay) { 0.25 }
|
18
26
|
|
19
27
|
before(:each) do
|
20
28
|
Spec::Support::EndpointFaker::FakerAPI.clear_requests!
|
@@ -22,20 +30,25 @@ describe Grape::Middleware::Async do
|
|
22
30
|
|
23
31
|
context "server async requests", type: :feature do
|
24
32
|
|
25
|
-
let(:reqs_tracker)
|
26
|
-
let(:async_responses) { %w(start start start done done done) }
|
27
|
-
let(:sync_responses) { %w(start done start done start done) }
|
33
|
+
let(:reqs_tracker) { Spec::Support::EndpointFaker::FakerAPI.requests }
|
34
|
+
let(:async_responses) { %w(start:1 start:2 start:3 done:1 done:2 done:3) }
|
35
|
+
let(:sync_responses) { %w(start:1 done:1 start:2 done:2 start:3 done:3) }
|
28
36
|
|
29
37
|
shared_examples "async requests" do
|
30
38
|
|
31
39
|
let(:route) { '/async' }
|
32
|
-
|
40
|
+
|
33
41
|
it "should make 3 thread based async requests" do
|
34
42
|
threads = []
|
43
|
+
counter = 0
|
44
|
+
expect(@server).to be_alive
|
35
45
|
3.times do
|
36
46
|
threads << Thread.new {
|
37
|
-
|
47
|
+
counter += 1
|
48
|
+
uri = URI.parse("http://#{host}:#{port}#{route}?counter=#{counter}&delay=#{delay}")
|
49
|
+
response = Net::HTTP.get_response(uri)
|
38
50
|
}
|
51
|
+
sleep(delay / 3.0)
|
39
52
|
end
|
40
53
|
threads.each(&:join)
|
41
54
|
expect(reqs_tracker).to eql(async_responses)
|
@@ -49,10 +62,14 @@ describe Grape::Middleware::Async do
|
|
49
62
|
|
50
63
|
it "should make sync 3 requests" do
|
51
64
|
threads = []
|
65
|
+
counter = 0
|
52
66
|
3.times do
|
53
67
|
threads << Thread.new {
|
54
|
-
|
68
|
+
counter += 1
|
69
|
+
uri = URI.parse("http://#{host}:#{port}#{route}?counter=#{counter}")
|
70
|
+
response = Net::HTTP.get_response(uri)
|
55
71
|
}
|
72
|
+
sleep(delay/3.0)
|
56
73
|
end
|
57
74
|
threads.each(&:join)
|
58
75
|
expect(reqs_tracker).to eql(sync_responses)
|
@@ -64,13 +81,13 @@ describe Grape::Middleware::Async do
|
|
64
81
|
|
65
82
|
before(:all) do
|
66
83
|
@server = Thread.new {
|
67
|
-
Thin::Server.start('localhost',
|
84
|
+
Thin::Server.start('localhost', port) { run Spec::Support::EndpointFaker::FakerAPI }
|
68
85
|
}
|
69
86
|
sleep(1)
|
70
87
|
end
|
71
88
|
|
72
89
|
after(:all) do
|
73
|
-
|
90
|
+
kill_server
|
74
91
|
end
|
75
92
|
|
76
93
|
context "sync endpoints are run as sync" do
|
@@ -92,16 +109,17 @@ describe Grape::Middleware::Async do
|
|
92
109
|
context "using the puma server" do
|
93
110
|
|
94
111
|
before(:all) do
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
112
|
+
app = Spec::Support::EndpointFaker::FakerAPI.new
|
113
|
+
puma = Puma::Server.new(app).tap do |s|
|
114
|
+
s.add_tcp_listener 'localhost', port
|
115
|
+
end
|
116
|
+
puma.run
|
117
|
+
@server = puma.thread
|
118
|
+
sleep(1)
|
101
119
|
end
|
102
120
|
|
103
121
|
after(:all) do
|
104
|
-
|
122
|
+
kill_server
|
105
123
|
end
|
106
124
|
|
107
125
|
context "sync endpoints are run as sync" do
|
@@ -131,13 +149,13 @@ describe Grape::Middleware::Async do
|
|
131
149
|
|
132
150
|
before(:all) do
|
133
151
|
@server = Thread.new {
|
134
|
-
Rack::Handler::WEBrick.run(Spec::Support::EndpointFaker::FakerAPI.new, :Port =>
|
152
|
+
Rack::Handler::WEBrick.run(Spec::Support::EndpointFaker::FakerAPI.new, :Port => port)
|
135
153
|
}
|
136
154
|
sleep(1)
|
137
155
|
end
|
138
156
|
|
139
157
|
after(:all) do
|
140
|
-
|
158
|
+
kill_server
|
141
159
|
end
|
142
160
|
|
143
161
|
context "sync endpoints are run as sync" do
|
@@ -160,38 +178,39 @@ describe Grape::Middleware::Async do
|
|
160
178
|
run Spec::Support::EndpointFaker::FakerAPI.new
|
161
179
|
end
|
162
180
|
}
|
181
|
+
let(:counter) { 1 }
|
163
182
|
|
164
183
|
context "async endpoints" do
|
165
184
|
it "should pass through the async middleware" do
|
166
|
-
expect_any_instance_of(Grape::
|
185
|
+
expect_any_instance_of(Grape::Async).to receive(:call!).and_return([-1, {}, []])
|
167
186
|
get '/async'
|
168
187
|
end
|
169
188
|
|
170
189
|
it "should receive async response" do
|
171
190
|
setup_async_obj!
|
172
|
-
get '/async'
|
191
|
+
get '/async', counter: counter, delay: delay
|
173
192
|
expect(last_response.status).to eq(-1)
|
174
193
|
end
|
175
194
|
|
176
195
|
it "should NOT receive async response without server asysnc support" do
|
177
|
-
get '/async'
|
196
|
+
get '/async', counter: counter, delay: delay
|
178
197
|
expect(last_response.status).to eq(200)
|
179
198
|
end
|
180
199
|
end
|
181
200
|
|
182
201
|
context "sync endpoints" do
|
183
202
|
it "should pass through the async middleware" do
|
184
|
-
expect_any_instance_of(Grape::
|
185
|
-
get '/sync'
|
203
|
+
expect_any_instance_of(Grape::Async).to receive(:call!).and_return([200, {}, ['ok']])
|
204
|
+
get '/sync', counter: counter
|
186
205
|
end
|
187
206
|
|
188
207
|
it "should NOT receive async response" do
|
189
|
-
get '/sync'
|
208
|
+
get '/sync', counter: counter
|
190
209
|
expect(last_response.status).to eq(200)
|
191
210
|
end
|
192
211
|
|
193
212
|
it "should NOT receive async response without server asysnc support" do
|
194
|
-
get '/sync'
|
213
|
+
get '/sync', counter: counter
|
195
214
|
expect(last_response.status).to eq(200)
|
196
215
|
end
|
197
216
|
|
@@ -19,46 +19,51 @@ module Spec
|
|
19
19
|
|
20
20
|
end
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
use Rack::CommonLogger
|
25
|
-
|
22
|
+
use Grape::Async
|
23
|
+
|
26
24
|
helpers do
|
27
|
-
def
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
def log_before!
|
32
|
-
FakerAPI.requests << "start"
|
25
|
+
def log_start!(i)
|
26
|
+
FakerAPI.requests << "start:#{i}"
|
33
27
|
end
|
34
28
|
|
35
|
-
def log_done!
|
36
|
-
FakerAPI.requests << "done"
|
29
|
+
def log_done!(i)
|
30
|
+
FakerAPI.requests << "done:#{i}"
|
37
31
|
end
|
38
32
|
end
|
39
33
|
|
40
34
|
async
|
35
|
+
params do
|
36
|
+
requires :counter, type: Integer
|
37
|
+
requires :delay, type: Float
|
38
|
+
end
|
41
39
|
get :async do
|
42
|
-
|
43
|
-
sleep(
|
40
|
+
log_start!(params[:counter])
|
41
|
+
sleep(params[:delay])
|
44
42
|
present({ status: 'ok'})
|
45
|
-
log_done!
|
43
|
+
log_done!(params[:counter])
|
46
44
|
end
|
47
45
|
|
48
46
|
async :em
|
47
|
+
params do
|
48
|
+
requires :counter, type: Integer
|
49
|
+
requires :delay, type: Float
|
50
|
+
end
|
49
51
|
get :async_em do
|
50
|
-
|
51
|
-
EM.add_timer(
|
52
|
+
log_start!(params[:counter])
|
53
|
+
EM.add_timer(params[:delay]) do
|
52
54
|
present({ status: 'ok'})
|
53
55
|
done
|
54
|
-
log_done!
|
56
|
+
log_done!(params[:counter])
|
55
57
|
end
|
56
58
|
end
|
57
59
|
|
60
|
+
params do
|
61
|
+
requires :counter, type: Integer
|
62
|
+
end
|
58
63
|
get :sync do
|
59
|
-
|
64
|
+
log_start!(params[:counter])
|
60
65
|
present({ status: 'ok'})
|
61
|
-
log_done!
|
66
|
+
log_done!(params[:counter])
|
62
67
|
end
|
63
68
|
|
64
69
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grape-async
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lachlan Laycock
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: grape
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '1.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '1.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rake
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,13 +128,13 @@ files:
|
|
128
128
|
- grape-async.gemspec
|
129
129
|
- lib/.DS_Store
|
130
130
|
- lib/grape-async.rb
|
131
|
-
- lib/grape-async/
|
131
|
+
- lib/grape-async/async.rb
|
132
132
|
- lib/grape-async/endpoint.rb
|
133
|
-
- lib/grape-async/
|
133
|
+
- lib/grape-async/extension.rb
|
134
134
|
- spec/factories.rb
|
135
135
|
- spec/lib/grape-async/api_spec.rb
|
136
|
+
- spec/lib/grape-async/async_spec.rb
|
136
137
|
- spec/lib/grape-async/endpoint_spec.rb
|
137
|
-
- spec/lib/grape-async/middleware/async_spec.rb
|
138
138
|
- spec/spec_helper.rb
|
139
139
|
- spec/support/endpoint_faker.rb
|
140
140
|
homepage: https://github.com/stuartapp/grape-async
|
@@ -157,7 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
157
157
|
version: '0'
|
158
158
|
requirements: []
|
159
159
|
rubyforge_project:
|
160
|
-
rubygems_version: 2.
|
160
|
+
rubygems_version: 2.5.1
|
161
161
|
signing_key:
|
162
162
|
specification_version: 4
|
163
163
|
summary: Enable asyncronous endpoints to avoid blocking slow requests within EventMachine
|
@@ -165,7 +165,7 @@ summary: Enable asyncronous endpoints to avoid blocking slow requests within Eve
|
|
165
165
|
test_files:
|
166
166
|
- spec/factories.rb
|
167
167
|
- spec/lib/grape-async/api_spec.rb
|
168
|
+
- spec/lib/grape-async/async_spec.rb
|
168
169
|
- spec/lib/grape-async/endpoint_spec.rb
|
169
|
-
- spec/lib/grape-async/middleware/async_spec.rb
|
170
170
|
- spec/spec_helper.rb
|
171
171
|
- spec/support/endpoint_faker.rb
|
@@ -1,71 +0,0 @@
|
|
1
|
-
module Grape
|
2
|
-
module Middleware
|
3
|
-
class Async < Grape::Middleware::Base
|
4
|
-
|
5
|
-
def call!(env)
|
6
|
-
@env = env
|
7
|
-
if endpoint.async_route? && !async_io.nil?
|
8
|
-
if endpoint.async_route?(:em)
|
9
|
-
proc = lambda {
|
10
|
-
EM.next_tick do
|
11
|
-
super
|
12
|
-
endpoint.deferred_resp.callback do
|
13
|
-
resp = endpoint.file || [endpoint.body]
|
14
|
-
async_call [endpoint.status, endpoint.header, resp]
|
15
|
-
end
|
16
|
-
end
|
17
|
-
}
|
18
|
-
if !EM.reactor_running?
|
19
|
-
EM.run do
|
20
|
-
proc.call
|
21
|
-
end
|
22
|
-
else
|
23
|
-
proc.call
|
24
|
-
end
|
25
|
-
else
|
26
|
-
Thread.new do
|
27
|
-
result = super
|
28
|
-
async_call result
|
29
|
-
yield
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
[-1, {}, []] # Return async response
|
34
|
-
|
35
|
-
else
|
36
|
-
super
|
37
|
-
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def async_call(result)
|
42
|
-
if @env['async.callback']
|
43
|
-
async_io.call result
|
44
|
-
elsif @env['rack.hijack']
|
45
|
-
begin
|
46
|
-
if result.last.is_a?(Rack::BodyProxy)
|
47
|
-
async_io << result.last.body.first
|
48
|
-
result.last.close unless result.last.closed?
|
49
|
-
elsif result.last.is_a?(Array)
|
50
|
-
async_io << result.last.first
|
51
|
-
end
|
52
|
-
ensure
|
53
|
-
EM.stop if endpoint.async_route?(:em)
|
54
|
-
@env['rack.hijack'].close
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def async_io
|
60
|
-
@env['async.callback'] || begin
|
61
|
-
@env.key?('rack.hijack') ? @env['rack.hijack'].call : nil
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def endpoint
|
66
|
-
@env[Grape::Env::API_ENDPOINT]
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|