graphql 0.8.1 → 0.9.2
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/lib/graphql.rb +0 -1
- data/lib/graphql/query.rb +0 -1
- data/lib/graphql/query/base_execution.rb +0 -6
- data/lib/graphql/query/context.rb +0 -4
- data/lib/graphql/query/executor.rb +2 -2
- data/lib/graphql/schema.rb +4 -1
- data/lib/graphql/version.rb +1 -1
- data/readme.md +1 -1
- data/spec/support/dairy_app.rb +2 -4
- metadata +1 -20
- data/lib/graphql/query/parallel_execution.rb +0 -102
- data/spec/graphql/query/parallel_execution_spec.rb +0 -29
- data/spec/support/parallel_schema.rb +0 -31
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 443760bcd1ca8e0c763ba9216cfc511c8c3d1185
|
|
4
|
+
data.tar.gz: df070125ce170c79d75bb7f5abe4c4303aaf6332
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9bbe4e2c99893d0bbb4d68ede2bff4acb9e3f8f11b9ff339a4e159db0baf4ccea21f3168ca69eb3cfb1737528f7dcf1a389df2f219b397c1a321416c061ab2af
|
|
7
|
+
data.tar.gz: ed66af0387e274413d89bed95e9b1f4e36c5d90b542505759046f53d8b6a310894a09f0ca4197872eab1b50bda74b01ad1a745a80f149fba042a8628d02ebfad
|
data/lib/graphql.rb
CHANGED
data/lib/graphql/query.rb
CHANGED
|
@@ -53,7 +53,6 @@ end
|
|
|
53
53
|
require 'graphql/query/arguments'
|
|
54
54
|
require 'graphql/query/base_execution'
|
|
55
55
|
require 'graphql/query/serial_execution'
|
|
56
|
-
require 'graphql/query/parallel_execution'
|
|
57
56
|
require 'graphql/query/type_resolver'
|
|
58
57
|
require 'graphql/query/directive_chain'
|
|
59
58
|
require 'graphql/query/executor'
|
|
@@ -31,10 +31,10 @@ module GraphQL
|
|
|
31
31
|
operation = find_operation(operation_name, query.operations)
|
|
32
32
|
if operation.operation_type == "query"
|
|
33
33
|
root_type = query.schema.query
|
|
34
|
-
execution_strategy_class = query.schema.query_execution_strategy
|
|
34
|
+
execution_strategy_class = query.schema.query_execution_strategy
|
|
35
35
|
elsif operation.operation_type == "mutation"
|
|
36
36
|
root_type = query.schema.mutation
|
|
37
|
-
execution_strategy_class =
|
|
37
|
+
execution_strategy_class = query.schema.mutation_execution_strategy
|
|
38
38
|
end
|
|
39
39
|
execution_strategy = execution_strategy_class.new
|
|
40
40
|
query.context.execution_strategy = execution_strategy
|
data/lib/graphql/schema.rb
CHANGED
|
@@ -4,7 +4,7 @@ class GraphQL::Schema
|
|
|
4
4
|
DYNAMIC_FIELDS = ["__type", "__typename", "__schema"]
|
|
5
5
|
|
|
6
6
|
attr_reader :query, :mutation, :directives, :static_validator
|
|
7
|
-
# Override these if you don't want the default
|
|
7
|
+
# Override these if you don't want the default executor:
|
|
8
8
|
attr_accessor :query_execution_strategy, :mutation_execution_strategy
|
|
9
9
|
|
|
10
10
|
|
|
@@ -15,6 +15,9 @@ class GraphQL::Schema
|
|
|
15
15
|
@mutation = mutation
|
|
16
16
|
@directives = DIRECTIVES.reduce({}) { |m, d| m[d.name] = d; m }
|
|
17
17
|
@static_validator = GraphQL::StaticValidation::Validator.new(schema: self)
|
|
18
|
+
# Default to the built-in execution strategy:
|
|
19
|
+
self.query_execution_strategy = GraphQL::Query::SerialExecution
|
|
20
|
+
self.mutation_execution_strategy = GraphQL::Query::SerialExecution
|
|
18
21
|
end
|
|
19
22
|
|
|
20
23
|
# A `{ name => type }` hash of types in this schema
|
data/lib/graphql/version.rb
CHANGED
data/readme.md
CHANGED
|
@@ -123,7 +123,7 @@ If you're building a backend for [Relay](http://facebook.github.io/relay/), you'
|
|
|
123
123
|
- `graphql-ruby` + Rails demo ([src](https://github.com/rmosolgo/graphql-ruby-demo) / [heroku](http://graphql-ruby-demo.herokuapp.com))
|
|
124
124
|
- [GraphQL Slack](https://graphql-slack.herokuapp.com/)
|
|
125
125
|
- [Example Relay support](https://github.com/rmosolgo/graphql-relay-ruby) in Ruby
|
|
126
|
-
- [`graphql-parallel`]
|
|
126
|
+
- [`graphql-parallel`](https://github.com/rmosolgo/graphql-parallel), an asynchronous query execution strategy
|
|
127
127
|
|
|
128
128
|
## P.S.
|
|
129
129
|
|
data/spec/support/dairy_app.rb
CHANGED
|
@@ -41,9 +41,7 @@ CheeseType = GraphQL::ObjectType.define do
|
|
|
41
41
|
description("Cheeses like this one")
|
|
42
42
|
argument :source, !types[!DairyAnimalEnum]
|
|
43
43
|
resolve -> (t, a, c) {
|
|
44
|
-
c.
|
|
45
|
-
CHEESES.values.find { |c| c.source == a["source"] }
|
|
46
|
-
end
|
|
44
|
+
CHEESES.values.find { |c| c.source == a["source"] }
|
|
47
45
|
}
|
|
48
46
|
end
|
|
49
47
|
|
|
@@ -161,7 +159,7 @@ QueryType = GraphQL::ObjectType.define do
|
|
|
161
159
|
field :error do
|
|
162
160
|
description "Raise an error"
|
|
163
161
|
type GraphQL::STRING_TYPE
|
|
164
|
-
resolve -> (t, a, c) {
|
|
162
|
+
resolve -> (t, a, c) { raise("This error was raised on purpose") }
|
|
165
163
|
end
|
|
166
164
|
|
|
167
165
|
# To test possibly-null fields
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: graphql
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.9.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Robert Mosolgo
|
|
@@ -24,20 +24,6 @@ dependencies:
|
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '1.6'
|
|
27
|
-
- !ruby/object:Gem::Dependency
|
|
28
|
-
name: celluloid
|
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
|
30
|
-
requirements:
|
|
31
|
-
- - "~>"
|
|
32
|
-
- !ruby/object:Gem::Version
|
|
33
|
-
version: '0.17'
|
|
34
|
-
type: :runtime
|
|
35
|
-
prerelease: false
|
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
-
requirements:
|
|
38
|
-
- - "~>"
|
|
39
|
-
- !ruby/object:Gem::Version
|
|
40
|
-
version: '0.17'
|
|
41
27
|
- !ruby/object:Gem::Dependency
|
|
42
28
|
name: codeclimate-test-reporter
|
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -227,7 +213,6 @@ files:
|
|
|
227
213
|
- lib/graphql/query/context.rb
|
|
228
214
|
- lib/graphql/query/directive_chain.rb
|
|
229
215
|
- lib/graphql/query/executor.rb
|
|
230
|
-
- lib/graphql/query/parallel_execution.rb
|
|
231
216
|
- lib/graphql/query/serial_execution.rb
|
|
232
217
|
- lib/graphql/query/serial_execution/field_resolution.rb
|
|
233
218
|
- lib/graphql/query/serial_execution/fragment_spread_resolution.rb
|
|
@@ -288,7 +273,6 @@ files:
|
|
|
288
273
|
- spec/graphql/language/visitor_spec.rb
|
|
289
274
|
- spec/graphql/object_type_spec.rb
|
|
290
275
|
- spec/graphql/query/executor_spec.rb
|
|
291
|
-
- spec/graphql/query/parallel_execution_spec.rb
|
|
292
276
|
- spec/graphql/query_spec.rb
|
|
293
277
|
- spec/graphql/schema/field_validator_spec.rb
|
|
294
278
|
- spec/graphql/schema/type_reducer_spec.rb
|
|
@@ -315,7 +299,6 @@ files:
|
|
|
315
299
|
- spec/spec_helper.rb
|
|
316
300
|
- spec/support/dairy_app.rb
|
|
317
301
|
- spec/support/dairy_data.rb
|
|
318
|
-
- spec/support/parallel_schema.rb
|
|
319
302
|
- spec/support/star_wars_data.rb
|
|
320
303
|
- spec/support/star_wars_schema.rb
|
|
321
304
|
homepage: http://github.com/rmosolgo/graphql-ruby
|
|
@@ -359,7 +342,6 @@ test_files:
|
|
|
359
342
|
- spec/graphql/language/visitor_spec.rb
|
|
360
343
|
- spec/graphql/object_type_spec.rb
|
|
361
344
|
- spec/graphql/query/executor_spec.rb
|
|
362
|
-
- spec/graphql/query/parallel_execution_spec.rb
|
|
363
345
|
- spec/graphql/query_spec.rb
|
|
364
346
|
- spec/graphql/schema/field_validator_spec.rb
|
|
365
347
|
- spec/graphql/schema/type_reducer_spec.rb
|
|
@@ -386,6 +368,5 @@ test_files:
|
|
|
386
368
|
- spec/spec_helper.rb
|
|
387
369
|
- spec/support/dairy_app.rb
|
|
388
370
|
- spec/support/dairy_data.rb
|
|
389
|
-
- spec/support/parallel_schema.rb
|
|
390
371
|
- spec/support/star_wars_data.rb
|
|
391
372
|
- spec/support/star_wars_schema.rb
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
module GraphQL
|
|
2
|
-
class Query
|
|
3
|
-
# Utilize Celluloid::Future to run field resolution in parallel.
|
|
4
|
-
class ParallelExecution < GraphQL::Query::BaseExecution
|
|
5
|
-
def initialize
|
|
6
|
-
# Why isn't `require "celluloid/current"` enough here?
|
|
7
|
-
Celluloid.boot unless Celluloid.running?
|
|
8
|
-
@has_futures = false
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def pool
|
|
12
|
-
@pool ||= ExecutionPool.run!
|
|
13
|
-
@pool[:execution_worker_pool]
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def async(block)
|
|
17
|
-
@has_futures ||= true
|
|
18
|
-
warn("GraphQL::Query::ParallelExecution has been extracted to the `graphql-parallel` gem, use that instead!")
|
|
19
|
-
pool.future.resolve(block)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def has_futures?
|
|
23
|
-
@has_futures
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
class OperationResolution < GraphQL::Query::SerialExecution::OperationResolution
|
|
27
|
-
def result
|
|
28
|
-
result_futures = super
|
|
29
|
-
if execution_strategy.has_futures?
|
|
30
|
-
finished_result = finish_all_futures(result_futures)
|
|
31
|
-
else
|
|
32
|
-
# Don't bother re-traversing the result if there are no futures.
|
|
33
|
-
finished_result = result_futures
|
|
34
|
-
end
|
|
35
|
-
ensure
|
|
36
|
-
execution_strategy.pool.terminate
|
|
37
|
-
finished_result
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# Recurse over `result_object`, finding any futures and
|
|
41
|
-
# getting their finished values.
|
|
42
|
-
def finish_all_futures(result_object)
|
|
43
|
-
if result_object.is_a?(FutureFieldResolution)
|
|
44
|
-
resolved_value = finish_all_futures(result_object.result)
|
|
45
|
-
elsif result_object.is_a?(Hash)
|
|
46
|
-
result_object.each do |key, value|
|
|
47
|
-
result_object[key] = finish_all_futures(value)
|
|
48
|
-
end
|
|
49
|
-
resolved_value = result_object
|
|
50
|
-
elsif result_object.is_a?(Array)
|
|
51
|
-
resolved_value = result_object.map { |v| finish_all_futures(v) }
|
|
52
|
-
else
|
|
53
|
-
resolved_value = result_object
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
class SelectionResolution < GraphQL::Query::SerialExecution::SelectionResolution
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
class FieldResolution < GraphQL::Query::SerialExecution::FieldResolution
|
|
62
|
-
def get_finished_value(raw_value)
|
|
63
|
-
if raw_value.is_a?(Celluloid::Future)
|
|
64
|
-
GraphQL::Query::ParallelExecution::FutureFieldResolution.new(field_resolution: self, future: raw_value)
|
|
65
|
-
else
|
|
66
|
-
super
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
class InlineFragmentResolution < GraphQL::Query::SerialExecution::InlineFragmentResolution
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
class FragmentSpreadResolution < GraphQL::Query::SerialExecution::FragmentSpreadResolution
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
class ExecutionWorker
|
|
78
|
-
include Celluloid
|
|
79
|
-
def resolve(proc)
|
|
80
|
-
proc.call
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
class ExecutionPool < Celluloid::Supervision::Container
|
|
85
|
-
pool ExecutionWorker, as: :execution_worker_pool
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
class FutureFieldResolution
|
|
89
|
-
def initialize(field_resolution:, future:)
|
|
90
|
-
@field_resolution = field_resolution
|
|
91
|
-
@future = future
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def result
|
|
95
|
-
resolved_value = @future.value
|
|
96
|
-
result_value = @field_resolution.get_finished_value(resolved_value)
|
|
97
|
-
result_value
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
end
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe GraphQL::Query::ParallelExecution do
|
|
4
|
-
let(:result) { GraphQL::Query.new(SlowSchema, query_string).result }
|
|
5
|
-
describe "fields that take a long time" do
|
|
6
|
-
let(:query_string) {%|
|
|
7
|
-
{
|
|
8
|
-
slow1: slow { slow1, slow2, slows { slow1 } }
|
|
9
|
-
slow2: slow { slow1, slow2, lastSlow: slow3 }
|
|
10
|
-
}
|
|
11
|
-
|}
|
|
12
|
-
|
|
13
|
-
it "runs them in parallel, not in sequence" do
|
|
14
|
-
elapsed = Benchmark.realtime { result }
|
|
15
|
-
assert elapsed < 0.7, "It takes less that the sum of all sleeps"
|
|
16
|
-
|
|
17
|
-
expected = { "data" => {
|
|
18
|
-
"slow1" => { "slow1" => 1, "slow2" => 1, "slows" => [
|
|
19
|
-
{ "slow1" => 1 },
|
|
20
|
-
{ "slow1" => 1 },
|
|
21
|
-
{ "slow1" => 1 },
|
|
22
|
-
]
|
|
23
|
-
},
|
|
24
|
-
"slow2" => { "slow1" => 1, "slow2" => 1, "lastSlow" => 1},
|
|
25
|
-
}}
|
|
26
|
-
assert_equal expected, result, "It renders the right result"
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
def create_slow_field
|
|
3
|
-
GraphQL::Field.define do
|
|
4
|
-
type(types.Int)
|
|
5
|
-
resolve -> (obj, args, ctx) {
|
|
6
|
-
ctx.async {
|
|
7
|
-
sleep 0.3
|
|
8
|
-
1
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
SlowType = GraphQL::ObjectType.define do
|
|
15
|
-
name "Slow"
|
|
16
|
-
field :slow1, field: create_slow_field
|
|
17
|
-
field :slow2, field: create_slow_field
|
|
18
|
-
field :slow3, field: create_slow_field
|
|
19
|
-
field :slows, -> { types[SlowType] } do
|
|
20
|
-
resolve -> (o, a, ctx) { ctx.async { [:slow, :slow, :slow] } }
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
SlowQueryType = GraphQL::ObjectType.define do
|
|
25
|
-
name "Query"
|
|
26
|
-
field :slow, SlowType do
|
|
27
|
-
resolve -> (o, a, c) { :slow }
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
SlowSchema = GraphQL::Schema.new(query: SlowQueryType)
|