Skip to content

Commit fbc5b37

Browse files
authored
graphql-ruby lazy_resolve, Async::Semaphore (#4)
1 parent d47bc37 commit fbc5b37

File tree

8 files changed

+222
-0
lines changed

8 files changed

+222
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
2.7.2
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
source "https://rubygems.org"
2+
3+
ruby "2.7.2"
4+
5+
gem "rack"
6+
gem "falcon"
7+
gem "async-http"
8+
gem "graphql"
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
GEM
2+
remote: https://rubygems.org/
3+
specs:
4+
async (1.28.7)
5+
console (~> 1.10)
6+
nio4r (~> 2.3)
7+
timers (~> 4.1)
8+
async-container (0.16.8)
9+
async (~> 1.0)
10+
async-io (~> 1.26)
11+
async-http (0.54.1)
12+
async (~> 1.25)
13+
async-io (~> 1.28)
14+
async-pool (~> 0.2)
15+
protocol-http (~> 0.21.0)
16+
protocol-http1 (~> 0.13.0)
17+
protocol-http2 (~> 0.14.0)
18+
async-http-cache (0.3.0)
19+
async-http (~> 0.53)
20+
async-io (1.30.2)
21+
async (~> 1.14)
22+
async-pool (0.3.4)
23+
async (~> 1.25)
24+
build-environment (1.13.0)
25+
console (1.10.1)
26+
fiber-local
27+
falcon (0.37.2)
28+
async (~> 1.13)
29+
async-container (~> 0.16.0)
30+
async-http (~> 0.54.0)
31+
async-http-cache (~> 0.3.0)
32+
async-io (~> 1.22)
33+
build-environment (~> 1.13)
34+
bundler
35+
localhost (~> 1.1)
36+
process-metrics (~> 0.2.0)
37+
rack (>= 1.0)
38+
samovar (~> 2.1)
39+
fiber-local (1.0.0)
40+
graphql (1.12.4)
41+
graphql-batch (0.4.3)
42+
graphql (>= 1.3, < 2)
43+
promise.rb (~> 0.7.2)
44+
localhost (1.1.6)
45+
mapping (1.1.1)
46+
nio4r (2.5.5)
47+
process-metrics (0.2.1)
48+
console (~> 1.8)
49+
samovar (~> 2.1)
50+
promise.rb (0.7.4)
51+
protocol-hpack (1.4.2)
52+
protocol-http (0.21.0)
53+
protocol-http1 (0.13.2)
54+
protocol-http (~> 0.19)
55+
protocol-http2 (0.14.2)
56+
protocol-hpack (~> 1.4)
57+
protocol-http (~> 0.18)
58+
rack (2.2.3)
59+
samovar (2.1.4)
60+
console (~> 1.0)
61+
mapping (~> 1.0)
62+
timers (4.3.2)
63+
64+
PLATFORMS
65+
ruby
66+
67+
DEPENDENCIES
68+
async-http
69+
falcon
70+
graphql
71+
graphql-batch
72+
rack
73+
74+
RUBY VERSION
75+
ruby 2.7.2p137
76+
77+
BUNDLED WITH
78+
2.1.4
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
Example app using:
2+
* rack
3+
* falcon
4+
* async-http
5+
* graphql
6+
7+
Notes:
8+
* The same idea as rack-async-http-falcon-graphql, but...
9+
* Using lazy_resolve instead of a batch loader
10+
* Re: https://github.com/trevorturk/async-examples/issues/2
11+
12+
Running and benchmarking:
13+
14+
falcon serve --count 1
15+
ab -n 100 -c 100 https://localhost:9292/
16+
17+
Benchmark results:
18+
19+
Server Software:
20+
Server Hostname: localhost
21+
Server Port: 9292
22+
SSL/TLS Protocol: TLSv1.2,ECDHE-RSA-AES256-GCM-SHA384,2048,256
23+
Server Temp Key: ECDH P-256 256 bits
24+
TLS Server Name: localhost
25+
26+
Document Path: /
27+
Document Length: 120 bytes
28+
29+
Concurrency Level: 100
30+
Time taken for tests: 5.140 seconds
31+
Complete requests: 100
32+
Failed requests: 0
33+
Total transferred: 18300 bytes
34+
HTML transferred: 12000 bytes
35+
Requests per second: 19.45 [#/sec] (mean)
36+
Time per request: 5140.459 [ms] (mean)
37+
Time per request: 51.405 [ms] (mean, across all concurrent requests)
38+
Transfer rate: 3.48 [Kbytes/sec] received
39+
40+
Connection Times (ms)
41+
min mean[+/-sd] median max
42+
Connect: 45 219 64.6 270 273
43+
Processing: 2213 2287 67.8 2258 2570
44+
Waiting: 2213 2285 68.2 2258 2567
45+
Total: 2324 2506 71.4 2521 2821
46+
47+
Percentage of the requests served within a certain time (ms)
48+
50% 2521
49+
66% 2527
50+
75% 2528
51+
80% 2530
52+
90% 2605
53+
95% 2681
54+
98% 2687
55+
99% 2821
56+
100% 2821 (longest request)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
require_relative "schema"
2+
3+
class App
4+
def self.call(env)
5+
puts "Request start"
6+
7+
result = Schema.execute("query { one two three }")
8+
9+
puts "Request finish"
10+
11+
[200, {}, [result.to_json]]
12+
end
13+
end
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
require "rubygems"
2+
require "bundler"
3+
Bundler.require
4+
5+
require_relative "app"
6+
7+
run App
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
require "async/http/internet"
2+
3+
class Query < GraphQL::Schema::Object
4+
field :one, String, null: false
5+
field :two, String, null: false
6+
field :three, String, null: false
7+
8+
def one
9+
Async { delay_1_data["url"] }
10+
end
11+
12+
def two
13+
Async { delay_2_data["url"] }
14+
end
15+
16+
def three
17+
Async { delay_2_data["url"] }
18+
end
19+
20+
def internet
21+
@_internet ||= Async::HTTP::Internet.new
22+
end
23+
24+
def delay_1_semaphore
25+
@_delay_1_semaphore ||= Async::Semaphore.new
26+
end
27+
28+
def delay_2_semaphore
29+
@_delay_2_semaphore ||= Async::Semaphore.new
30+
end
31+
32+
def delay_1_data
33+
delay_1_semaphore.async do |task|
34+
@_delay_1_data ||= begin
35+
puts "-> delay_1_data"
36+
data = JSON.parse(internet.get("https://httpbin.org/delay/1").read)
37+
puts "<- delay_1_data"
38+
data
39+
end
40+
end.result
41+
end
42+
43+
def delay_2_data
44+
delay_2_semaphore.async do |task|
45+
@_delay_2_data ||= begin
46+
puts "-> delay_2_data"
47+
data = JSON.parse(internet.get("https://httpbin.org/delay/2").read)
48+
puts "<- delay_2_data"
49+
data
50+
end
51+
end.result
52+
end
53+
end
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
require_relative "query"
2+
3+
class Schema < GraphQL::Schema
4+
query Query
5+
lazy_resolve Async::Task, :wait
6+
end

0 commit comments

Comments
 (0)