diff --git a/rack-async-http-falcon-graphql-lazy-resolve/.ruby-version b/rack-async-http-falcon-graphql-lazy-resolve/.ruby-version new file mode 100644 index 0000000..37c2961 --- /dev/null +++ b/rack-async-http-falcon-graphql-lazy-resolve/.ruby-version @@ -0,0 +1 @@ +2.7.2 diff --git a/rack-async-http-falcon-graphql-lazy-resolve/Gemfile b/rack-async-http-falcon-graphql-lazy-resolve/Gemfile new file mode 100644 index 0000000..2fc9c13 --- /dev/null +++ b/rack-async-http-falcon-graphql-lazy-resolve/Gemfile @@ -0,0 +1,8 @@ +source "https://rubygems.org" + +ruby "2.7.2" + +gem "rack" +gem "falcon" +gem "async-http" +gem "graphql" diff --git a/rack-async-http-falcon-graphql-lazy-resolve/Gemfile.lock b/rack-async-http-falcon-graphql-lazy-resolve/Gemfile.lock new file mode 100644 index 0000000..eb211e5 --- /dev/null +++ b/rack-async-http-falcon-graphql-lazy-resolve/Gemfile.lock @@ -0,0 +1,78 @@ +GEM + remote: https://rubygems.org/ + specs: + async (1.28.7) + console (~> 1.10) + nio4r (~> 2.3) + timers (~> 4.1) + async-container (0.16.8) + async (~> 1.0) + async-io (~> 1.26) + async-http (0.54.1) + async (~> 1.25) + async-io (~> 1.28) + async-pool (~> 0.2) + protocol-http (~> 0.21.0) + protocol-http1 (~> 0.13.0) + protocol-http2 (~> 0.14.0) + async-http-cache (0.3.0) + async-http (~> 0.53) + async-io (1.30.2) + async (~> 1.14) + async-pool (0.3.4) + async (~> 1.25) + build-environment (1.13.0) + console (1.10.1) + fiber-local + falcon (0.37.2) + async (~> 1.13) + async-container (~> 0.16.0) + async-http (~> 0.54.0) + async-http-cache (~> 0.3.0) + async-io (~> 1.22) + build-environment (~> 1.13) + bundler + localhost (~> 1.1) + process-metrics (~> 0.2.0) + rack (>= 1.0) + samovar (~> 2.1) + fiber-local (1.0.0) + graphql (1.12.4) + graphql-batch (0.4.3) + graphql (>= 1.3, < 2) + promise.rb (~> 0.7.2) + localhost (1.1.6) + mapping (1.1.1) + nio4r (2.5.5) + process-metrics (0.2.1) + console (~> 1.8) + samovar (~> 2.1) + promise.rb (0.7.4) + protocol-hpack (1.4.2) + protocol-http (0.21.0) + protocol-http1 (0.13.2) + protocol-http (~> 0.19) + protocol-http2 (0.14.2) + protocol-hpack (~> 1.4) + protocol-http (~> 0.18) + rack (2.2.3) + samovar (2.1.4) + console (~> 1.0) + mapping (~> 1.0) + timers (4.3.2) + +PLATFORMS + ruby + +DEPENDENCIES + async-http + falcon + graphql + graphql-batch + rack + +RUBY VERSION + ruby 2.7.2p137 + +BUNDLED WITH + 2.1.4 diff --git a/rack-async-http-falcon-graphql-lazy-resolve/README.md b/rack-async-http-falcon-graphql-lazy-resolve/README.md new file mode 100644 index 0000000..b5bb2fc --- /dev/null +++ b/rack-async-http-falcon-graphql-lazy-resolve/README.md @@ -0,0 +1,56 @@ +Example app using: + * rack + * falcon + * async-http + * graphql + +Notes: + * The same idea as rack-async-http-falcon-graphql, but... + * Using lazy_resolve instead of a batch loader + * Re: https://github.com/trevorturk/async-examples/issues/2 + +Running and benchmarking: + + falcon serve --count 1 + ab -n 100 -c 100 https://localhost:9292/ + +Benchmark results: + + Server Software: + Server Hostname: localhost + Server Port: 9292 + SSL/TLS Protocol: TLSv1.2,ECDHE-RSA-AES256-GCM-SHA384,2048,256 + Server Temp Key: ECDH P-256 256 bits + TLS Server Name: localhost + + Document Path: / + Document Length: 120 bytes + + Concurrency Level: 100 + Time taken for tests: 5.140 seconds + Complete requests: 100 + Failed requests: 0 + Total transferred: 18300 bytes + HTML transferred: 12000 bytes + Requests per second: 19.45 [#/sec] (mean) + Time per request: 5140.459 [ms] (mean) + Time per request: 51.405 [ms] (mean, across all concurrent requests) + Transfer rate: 3.48 [Kbytes/sec] received + + Connection Times (ms) + min mean[+/-sd] median max + Connect: 45 219 64.6 270 273 + Processing: 2213 2287 67.8 2258 2570 + Waiting: 2213 2285 68.2 2258 2567 + Total: 2324 2506 71.4 2521 2821 + + Percentage of the requests served within a certain time (ms) + 50% 2521 + 66% 2527 + 75% 2528 + 80% 2530 + 90% 2605 + 95% 2681 + 98% 2687 + 99% 2821 + 100% 2821 (longest request) diff --git a/rack-async-http-falcon-graphql-lazy-resolve/app.rb b/rack-async-http-falcon-graphql-lazy-resolve/app.rb new file mode 100644 index 0000000..34a9104 --- /dev/null +++ b/rack-async-http-falcon-graphql-lazy-resolve/app.rb @@ -0,0 +1,13 @@ +require_relative "schema" + +class App + def self.call(env) + puts "Request start" + + result = Schema.execute("query { one two three }") + + puts "Request finish" + + [200, {}, [result.to_json]] + end +end diff --git a/rack-async-http-falcon-graphql-lazy-resolve/config.ru b/rack-async-http-falcon-graphql-lazy-resolve/config.ru new file mode 100644 index 0000000..b929d04 --- /dev/null +++ b/rack-async-http-falcon-graphql-lazy-resolve/config.ru @@ -0,0 +1,7 @@ +require "rubygems" +require "bundler" +Bundler.require + +require_relative "app" + +run App diff --git a/rack-async-http-falcon-graphql-lazy-resolve/query.rb b/rack-async-http-falcon-graphql-lazy-resolve/query.rb new file mode 100644 index 0000000..4751a35 --- /dev/null +++ b/rack-async-http-falcon-graphql-lazy-resolve/query.rb @@ -0,0 +1,53 @@ +require "async/http/internet" + +class Query < GraphQL::Schema::Object + field :one, String, null: false + field :two, String, null: false + field :three, String, null: false + + def one + Async { delay_1_data["url"] } + end + + def two + Async { delay_2_data["url"] } + end + + def three + Async { delay_2_data["url"] } + end + + def internet + @_internet ||= Async::HTTP::Internet.new + end + + def delay_1_semaphore + @_delay_1_semaphore ||= Async::Semaphore.new + end + + def delay_2_semaphore + @_delay_2_semaphore ||= Async::Semaphore.new + end + + def delay_1_data + delay_1_semaphore.async do |task| + @_delay_1_data ||= begin + puts "-> delay_1_data" + data = JSON.parse(internet.get("https://httpbin.org/delay/1").read) + puts "<- delay_1_data" + data + end + end.result + end + + def delay_2_data + delay_2_semaphore.async do |task| + @_delay_2_data ||= begin + puts "-> delay_2_data" + data = JSON.parse(internet.get("https://httpbin.org/delay/2").read) + puts "<- delay_2_data" + data + end + end.result + end +end diff --git a/rack-async-http-falcon-graphql-lazy-resolve/schema.rb b/rack-async-http-falcon-graphql-lazy-resolve/schema.rb new file mode 100644 index 0000000..4cbcafc --- /dev/null +++ b/rack-async-http-falcon-graphql-lazy-resolve/schema.rb @@ -0,0 +1,6 @@ +require_relative "query" + +class Schema < GraphQL::Schema + query Query + lazy_resolve Async::Task, :wait +end