grape-async 0.1.2 → 0.1.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.
- 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
|