graphql 2.5.9 → 2.5.26

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.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/detailed_trace_generator.rb +77 -0
  3. data/lib/generators/graphql/templates/create_graphql_detailed_traces.erb +10 -0
  4. data/lib/graphql/analysis.rb +20 -13
  5. data/lib/graphql/dashboard/application_controller.rb +41 -0
  6. data/lib/graphql/dashboard/landings_controller.rb +9 -0
  7. data/lib/graphql/dashboard/statics_controller.rb +31 -0
  8. data/lib/graphql/dashboard/subscriptions.rb +2 -1
  9. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/_form.html.erb +1 -0
  10. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/edit.html.erb +2 -2
  11. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/index.html.erb +1 -1
  12. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/new.html.erb +1 -1
  13. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/index.html.erb +1 -1
  14. data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/show.html.erb +1 -1
  15. data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/show.html.erb +1 -1
  16. data/lib/graphql/dashboard/views/layouts/graphql/dashboard/application.html.erb +7 -7
  17. data/lib/graphql/dashboard.rb +11 -73
  18. data/lib/graphql/dataloader/active_record_association_source.rb +14 -2
  19. data/lib/graphql/dataloader/async_dataloader.rb +22 -11
  20. data/lib/graphql/dataloader/null_dataloader.rb +54 -9
  21. data/lib/graphql/dataloader.rb +75 -23
  22. data/lib/graphql/date_encoding_error.rb +1 -1
  23. data/lib/graphql/execution/field_resolve_step.rb +631 -0
  24. data/lib/graphql/execution/finalize.rb +217 -0
  25. data/lib/graphql/execution/input_values.rb +261 -0
  26. data/lib/graphql/execution/interpreter/handles_raw_value.rb +6 -0
  27. data/lib/graphql/execution/interpreter/resolve.rb +10 -16
  28. data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +13 -0
  29. data/lib/graphql/execution/interpreter/runtime.rb +28 -33
  30. data/lib/graphql/execution/interpreter.rb +8 -22
  31. data/lib/graphql/execution/lazy.rb +1 -1
  32. data/lib/graphql/execution/load_argument_step.rb +64 -0
  33. data/lib/graphql/execution/multiplex.rb +1 -1
  34. data/lib/graphql/execution/next.rb +90 -0
  35. data/lib/graphql/execution/prepare_object_step.rb +128 -0
  36. data/lib/graphql/execution/runner.rb +410 -0
  37. data/lib/graphql/execution/selections_step.rb +91 -0
  38. data/lib/graphql/execution.rb +8 -4
  39. data/lib/graphql/execution_error.rb +17 -10
  40. data/lib/graphql/introspection/directive_type.rb +7 -3
  41. data/lib/graphql/introspection/dynamic_fields.rb +5 -1
  42. data/lib/graphql/introspection/entry_points.rb +11 -3
  43. data/lib/graphql/introspection/enum_value_type.rb +5 -5
  44. data/lib/graphql/introspection/field_type.rb +13 -5
  45. data/lib/graphql/introspection/input_value_type.rb +21 -13
  46. data/lib/graphql/introspection/type_type.rb +64 -28
  47. data/lib/graphql/invalid_null_error.rb +11 -5
  48. data/lib/graphql/language/document_from_schema_definition.rb +2 -1
  49. data/lib/graphql/language/lexer.rb +20 -9
  50. data/lib/graphql/language/nodes.rb +5 -1
  51. data/lib/graphql/language/parser.rb +1 -0
  52. data/lib/graphql/language.rb +21 -12
  53. data/lib/graphql/pagination/connection.rb +2 -0
  54. data/lib/graphql/pagination/connections.rb +32 -0
  55. data/lib/graphql/query/context.rb +11 -4
  56. data/lib/graphql/query/null_context.rb +9 -3
  57. data/lib/graphql/query/partial.rb +18 -3
  58. data/lib/graphql/query.rb +10 -1
  59. data/lib/graphql/runtime_error.rb +6 -0
  60. data/lib/graphql/schema/addition.rb +3 -1
  61. data/lib/graphql/schema/argument.rb +17 -0
  62. data/lib/graphql/schema/build_from_definition.rb +15 -2
  63. data/lib/graphql/schema/directive.rb +45 -13
  64. data/lib/graphql/schema/field/connection_extension.rb +4 -37
  65. data/lib/graphql/schema/field/scope_extension.rb +18 -13
  66. data/lib/graphql/schema/field.rb +87 -48
  67. data/lib/graphql/schema/field_extension.rb +11 -8
  68. data/lib/graphql/schema/interface.rb +26 -0
  69. data/lib/graphql/schema/list.rb +5 -1
  70. data/lib/graphql/schema/member/base_dsl_methods.rb +1 -11
  71. data/lib/graphql/schema/member/has_arguments.rb +43 -14
  72. data/lib/graphql/schema/member/has_authorization.rb +35 -0
  73. data/lib/graphql/schema/member/has_dataloader.rb +37 -0
  74. data/lib/graphql/schema/member/has_fields.rb +86 -5
  75. data/lib/graphql/schema/member/has_interfaces.rb +2 -2
  76. data/lib/graphql/schema/member/type_system_helpers.rb +16 -2
  77. data/lib/graphql/schema/member.rb +5 -0
  78. data/lib/graphql/schema/non_null.rb +1 -1
  79. data/lib/graphql/schema/object.rb +1 -0
  80. data/lib/graphql/schema/ractor_shareable.rb +79 -0
  81. data/lib/graphql/schema/resolver.rb +60 -1
  82. data/lib/graphql/schema/subscription.rb +0 -2
  83. data/lib/graphql/schema/validator/required_validator.rb +45 -5
  84. data/lib/graphql/schema/visibility/migration.rb +2 -2
  85. data/lib/graphql/schema/visibility/profile.rb +140 -56
  86. data/lib/graphql/schema/visibility.rb +31 -18
  87. data/lib/graphql/schema/wrapper.rb +7 -1
  88. data/lib/graphql/schema.rb +108 -32
  89. data/lib/graphql/static_validation/all_rules.rb +1 -1
  90. data/lib/graphql/static_validation/base_visitor.rb +90 -66
  91. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
  92. data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +18 -6
  93. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +5 -2
  94. data/lib/graphql/static_validation/rules/directives_are_defined.rb +5 -2
  95. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +4 -3
  96. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +14 -4
  97. data/lib/graphql/static_validation/rules/fields_will_merge.rb +322 -256
  98. data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +4 -4
  99. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  100. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +10 -7
  101. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +27 -7
  102. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +6 -2
  103. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +12 -9
  104. data/lib/graphql/static_validation/validation_context.rb +1 -1
  105. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +1 -0
  106. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +34 -10
  107. data/lib/graphql/subscriptions/event.rb +1 -0
  108. data/lib/graphql/subscriptions.rb +36 -1
  109. data/lib/graphql/testing/helpers.rb +12 -9
  110. data/lib/graphql/testing/mock_action_cable.rb +111 -0
  111. data/lib/graphql/testing.rb +1 -0
  112. data/lib/graphql/tracing/detailed_trace/active_record_backend.rb +74 -0
  113. data/lib/graphql/tracing/detailed_trace.rb +70 -7
  114. data/lib/graphql/tracing/null_trace.rb +1 -1
  115. data/lib/graphql/tracing/perfetto_trace.rb +209 -79
  116. data/lib/graphql/tracing/sentry_trace.rb +3 -1
  117. data/lib/graphql/tracing/trace.rb +6 -0
  118. data/lib/graphql/type_kinds.rb +1 -0
  119. data/lib/graphql/types/relay/connection_behaviors.rb +8 -6
  120. data/lib/graphql/types/relay/edge_behaviors.rb +4 -3
  121. data/lib/graphql/types/relay/has_node_field.rb +13 -8
  122. data/lib/graphql/types/relay/has_nodes_field.rb +13 -8
  123. data/lib/graphql/types/relay/node_behaviors.rb +13 -2
  124. data/lib/graphql/unauthorized_error.rb +9 -1
  125. data/lib/graphql/version.rb +1 -1
  126. data/lib/graphql.rb +7 -3
  127. metadata +21 -3
@@ -64,6 +64,7 @@ module GraphQL
64
64
  @nonblocking = nonblocking
65
65
  end
66
66
  @fiber_limit = fiber_limit
67
+ @lazies_at_depth = Hash.new { |h, k| h[k] = [] }
67
68
  end
68
69
 
69
70
  # @return [Integer, nil]
@@ -140,10 +141,10 @@ module GraphQL
140
141
  end
141
142
 
142
143
  # @api private Nothing to see here
143
- def append_job(&job)
144
+ def append_job(callable = nil, &job)
144
145
  # Given a block, queue it up to be worked through when `#run` is called.
145
- # (If the dataloader is already running, than a Fiber will pick this up later.)
146
- @pending_jobs.push(job)
146
+ # (If the dataloader is already running, then a Fiber will pick this up later.)
147
+ @pending_jobs.push(callable || job)
147
148
  nil
148
149
  end
149
150
 
@@ -160,6 +161,10 @@ module GraphQL
160
161
  def run_isolated
161
162
  prev_queue = @pending_jobs
162
163
  prev_pending_keys = {}
164
+ prev_lazies_at_depth = @lazies_at_depth
165
+ @lazies_at_depth = @lazies_at_depth.dup.clear
166
+ # Clear pending loads but keep already-cached records
167
+ # in case they are useful to the given block.
163
168
  @source_cache.each do |source_class, batched_sources|
164
169
  batched_sources.each do |batch_args, batched_source_instance|
165
170
  if batched_source_instance.pending?
@@ -179,6 +184,7 @@ module GraphQL
179
184
  res
180
185
  ensure
181
186
  @pending_jobs = prev_queue
187
+ @lazies_at_depth = prev_lazies_at_depth
182
188
  prev_pending_keys.each do |source_instance, pending|
183
189
  pending.each do |key, value|
184
190
  if !source_instance.results.key?(key)
@@ -188,7 +194,8 @@ module GraphQL
188
194
  end
189
195
  end
190
196
 
191
- def run
197
+ # @param trace_query_lazy [nil, Execution::Multiplex]
198
+ def run(trace_query_lazy: nil)
192
199
  trace = Fiber[:__graphql_current_multiplex]&.current_trace
193
200
  jobs_fiber_limit, total_fiber_limit = calculate_fiber_limit
194
201
  job_fibers = []
@@ -201,26 +208,13 @@ module GraphQL
201
208
  while first_pass || !job_fibers.empty?
202
209
  first_pass = false
203
210
 
204
- while (f = (job_fibers.shift || (((next_job_fibers.size + job_fibers.size) < jobs_fiber_limit) && spawn_job_fiber(trace))))
205
- if f.alive?
206
- finished = run_fiber(f)
207
- if !finished
208
- next_job_fibers << f
209
- end
210
- end
211
- end
212
- join_queues(job_fibers, next_job_fibers)
213
-
214
- while (!source_fibers.empty? || @source_cache.each_value.any? { |group_sources| group_sources.each_value.any?(&:pending?) })
215
- while (f = source_fibers.shift || (((job_fibers.size + source_fibers.size + next_source_fibers.size + next_job_fibers.size) < total_fiber_limit) && spawn_source_fiber(trace)))
216
- if f.alive?
217
- finished = run_fiber(f)
218
- if !finished
219
- next_source_fibers << f
220
- end
221
- end
211
+ run_pending_steps(trace, job_fibers, next_job_fibers, jobs_fiber_limit, source_fibers, next_source_fibers, total_fiber_limit)
212
+
213
+ if !@lazies_at_depth.empty?
214
+ with_trace_query_lazy(trace_query_lazy) do
215
+ run_next_pending_lazies(job_fibers, trace)
216
+ run_pending_steps(trace, job_fibers, next_job_fibers, jobs_fiber_limit, source_fibers, next_source_fibers, total_fiber_limit)
222
217
  end
223
- join_queues(source_fibers, next_source_fibers)
224
218
  end
225
219
  end
226
220
 
@@ -248,6 +242,11 @@ module GraphQL
248
242
  f.resume
249
243
  end
250
244
 
245
+ # @api private
246
+ def lazy_at_depth(depth, lazy)
247
+ @lazies_at_depth[depth] << lazy
248
+ end
249
+
251
250
  def spawn_fiber
252
251
  fiber_vars = get_fiber_variables
253
252
  Fiber.new(blocking: !@nonblocking) {
@@ -275,6 +274,59 @@ module GraphQL
275
274
 
276
275
  private
277
276
 
277
+ def run_next_pending_lazies(job_fibers, trace)
278
+ smallest_depth = nil
279
+ @lazies_at_depth.each_key do |depth_key|
280
+ smallest_depth ||= depth_key
281
+ if depth_key < smallest_depth
282
+ smallest_depth = depth_key
283
+ end
284
+ end
285
+
286
+ if smallest_depth
287
+ lazies = @lazies_at_depth.delete(smallest_depth)
288
+ if !lazies.empty?
289
+ lazies.each_with_index do |l, idx|
290
+ append_job { l.value }
291
+ end
292
+ job_fibers.unshift(spawn_job_fiber(trace))
293
+ end
294
+ end
295
+ end
296
+
297
+ def run_pending_steps(trace, job_fibers, next_job_fibers, jobs_fiber_limit, source_fibers, next_source_fibers, total_fiber_limit)
298
+ while (f = (job_fibers.shift || (((next_job_fibers.size + job_fibers.size) < jobs_fiber_limit) && spawn_job_fiber(trace))))
299
+ if f.alive?
300
+ finished = run_fiber(f)
301
+ if !finished
302
+ next_job_fibers << f
303
+ end
304
+ end
305
+ end
306
+ join_queues(job_fibers, next_job_fibers)
307
+
308
+ while (!source_fibers.empty? || @source_cache.each_value.any? { |group_sources| group_sources.each_value.any?(&:pending?) })
309
+ while (f = source_fibers.shift || (((job_fibers.size + source_fibers.size + next_source_fibers.size + next_job_fibers.size) < total_fiber_limit) && spawn_source_fiber(trace)))
310
+ if f.alive?
311
+ finished = run_fiber(f)
312
+ if !finished
313
+ next_source_fibers << f
314
+ end
315
+ end
316
+ end
317
+ join_queues(source_fibers, next_source_fibers)
318
+ end
319
+ end
320
+
321
+ def with_trace_query_lazy(multiplex_or_nil, &block)
322
+ if (multiplex = multiplex_or_nil)
323
+ query = multiplex.queries.length == 1 ? multiplex.queries[0] : nil
324
+ multiplex.current_trace.execute_query_lazy(query: query, multiplex: multiplex, &block)
325
+ else
326
+ yield
327
+ end
328
+ end
329
+
278
330
  def calculate_fiber_limit
279
331
  total_fiber_limit = @fiber_limit || Float::INFINITY
280
332
  if total_fiber_limit < 4
@@ -10,7 +10,7 @@ module GraphQL
10
10
 
11
11
  def initialize(value)
12
12
  @date_value = value
13
- super("Date cannot be parsed: #{value}. \nDate must be be able to be parsed as a Ruby Date object.")
13
+ super("Date cannot be parsed: #{value}. \nDate must be able to be parsed as a Ruby Date object.")
14
14
  end
15
15
  end
16
16
  end