graphql 2.4.8 → 2.4.10

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graphql/backtrace/table.rb +95 -55
  3. data/lib/graphql/backtrace.rb +1 -19
  4. data/lib/graphql/current.rb +5 -0
  5. data/lib/graphql/dataloader/active_record_association_source.rb +64 -0
  6. data/lib/graphql/dataloader/active_record_source.rb +26 -0
  7. data/lib/graphql/dataloader/async_dataloader.rb +17 -5
  8. data/lib/graphql/dataloader/null_dataloader.rb +1 -1
  9. data/lib/graphql/dataloader/source.rb +2 -2
  10. data/lib/graphql/dataloader.rb +37 -5
  11. data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +11 -4
  12. data/lib/graphql/execution/interpreter/runtime.rb +59 -32
  13. data/lib/graphql/execution/interpreter.rb +9 -1
  14. data/lib/graphql/execution/multiplex.rb +0 -4
  15. data/lib/graphql/introspection/directive_location_enum.rb +1 -1
  16. data/lib/graphql/language/parser.rb +1 -1
  17. data/lib/graphql/query.rb +8 -12
  18. data/lib/graphql/schema/build_from_definition.rb +1 -0
  19. data/lib/graphql/schema/enum.rb +21 -1
  20. data/lib/graphql/schema/interface.rb +1 -0
  21. data/lib/graphql/schema/loader.rb +1 -0
  22. data/lib/graphql/schema/member/has_dataloader.rb +56 -0
  23. data/lib/graphql/schema/member.rb +1 -0
  24. data/lib/graphql/schema/object.rb +17 -8
  25. data/lib/graphql/schema/resolver.rb +2 -5
  26. data/lib/graphql/schema/validator/required_validator.rb +23 -6
  27. data/lib/graphql/schema/visibility/profile.rb +5 -5
  28. data/lib/graphql/schema/visibility.rb +14 -9
  29. data/lib/graphql/schema.rb +9 -25
  30. data/lib/graphql/static_validation/validator.rb +6 -1
  31. data/lib/graphql/subscriptions/serialize.rb +1 -3
  32. data/lib/graphql/tracing/appoptics_trace.rb +1 -1
  33. data/lib/graphql/tracing/new_relic_trace.rb +138 -41
  34. data/lib/graphql/tracing/perfetto_trace/trace.proto +141 -0
  35. data/lib/graphql/tracing/perfetto_trace/trace_pb.rb +33 -0
  36. data/lib/graphql/tracing/perfetto_trace.rb +726 -0
  37. data/lib/graphql/tracing/trace.rb +125 -1
  38. data/lib/graphql/tracing.rb +1 -0
  39. data/lib/graphql/version.rb +1 -1
  40. metadata +135 -10
  41. data/lib/graphql/backtrace/inspect_result.rb +0 -38
  42. data/lib/graphql/backtrace/trace.rb +0 -93
  43. data/lib/graphql/backtrace/tracer.rb +0 -80
  44. data/lib/graphql/schema/null_mask.rb +0 -11
@@ -8,7 +8,7 @@ module GraphQL
8
8
  # "Trace modes" are subclasses of this with custom tracing modules mixed in.
9
9
  #
10
10
  # A trace module may implement any of the methods on `Trace`, being sure to call `super`
11
- # to continue any tracing hooks and call the actual runtime behavior. See {GraphQL::Backtrace::Trace} for example.
11
+ # to continue any tracing hooks and call the actual runtime behavior.
12
12
  #
13
13
  class Trace
14
14
  # @param multiplex [GraphQL::Execution::Multiplex, nil]
@@ -23,6 +23,14 @@ module GraphQL
23
23
  yield
24
24
  end
25
25
 
26
+ # @param query_str [String]
27
+ # @return [void]
28
+ def begin_parse(query_str); end;
29
+ # @param query_str [String]
30
+ # @return [void]
31
+ def end_parse(query_str); end;
32
+ # @param query_string [String]
33
+ # @return [void]
26
34
  def parse(query_string:)
27
35
  yield
28
36
  end
@@ -31,6 +39,22 @@ module GraphQL
31
39
  yield
32
40
  end
33
41
 
42
+ def begin_validate(query, validate)
43
+ end
44
+
45
+ def end_validate(query, validate, errors)
46
+ end
47
+
48
+ # @param multiplex [GraphQL::Execution::Multiplex]
49
+ # @param analyzers [Array<Class>]
50
+ # @return [void]
51
+ def begin_analyze_multiplex(multiplex, analyzers); end
52
+ # @param multiplex [GraphQL::Execution::Multiplex]
53
+ # @param analyzers [Array<Class>]
54
+ # @return [void]
55
+ def end_analyze_multiplex(multiplex, analyzers); end
56
+ # @param multiplex [GraphQL::Execution::Multiplex]
57
+ # @return [void]
34
58
  def analyze_multiplex(multiplex:)
35
59
  yield
36
60
  end
@@ -39,6 +63,20 @@ module GraphQL
39
63
  yield
40
64
  end
41
65
 
66
+ # This is the first event in the tracing lifecycle.
67
+ # Every Query is technically run _inside_ a {GraphQL::Multiplex}.
68
+ # @param multiplex [GraphQL::Execution::Multiplex]
69
+ # @return [void]
70
+ def begin_execute_multiplex(multiplex); end;
71
+
72
+ # This is the last event of the tracing lifecycle.
73
+ # @param multiplex [GraphQL::Execution::Multiplex]
74
+ # @return [void]
75
+ def end_execute_multiplex(multiplex); end;
76
+
77
+ # This wraps an entire `.execute` call.
78
+ # @param multiplex [GraphQL::Execution::Multiplex]
79
+ # @return [void]
42
80
  def execute_multiplex(multiplex:)
43
81
  yield
44
82
  end
@@ -51,6 +89,20 @@ module GraphQL
51
89
  yield
52
90
  end
53
91
 
92
+ # GraphQL is about to resolve this field
93
+ # @param field [GraphQL::Schema::Field]
94
+ # @param object [GraphQL::Schema::Object]
95
+ # @param arguments [Hash]
96
+ # @param query [GraphQL::Query]
97
+ def begin_execute_field(field, object, arguments, query); end
98
+ # GraphQL just finished resolving this field
99
+ # @param field [GraphQL::Schema::Field]
100
+ # @param object [GraphQL::Schema::Object]
101
+ # @param arguments [Hash]
102
+ # @param query [GraphQL::Query]
103
+ # @param result [Object]
104
+ def end_execute_field(field, object, arguments, query, result); end
105
+
54
106
  def execute_field(field:, query:, ast_node:, arguments:, object:)
55
107
  yield
56
108
  end
@@ -63,6 +115,22 @@ module GraphQL
63
115
  yield
64
116
  end
65
117
 
118
+ # A call to `.authorized?` is starting
119
+ # @param type [Class<GraphQL::Schema::Object>]
120
+ # @param object [Object]
121
+ # @param context [GraphQL::Query::Context]
122
+ # @return [void]
123
+ def begin_authorized(type, object, context)
124
+ end
125
+ # A call to `.authorized?` just finished
126
+ # @param type [Class<GraphQL::Schema::Object>]
127
+ # @param object [Object]
128
+ # @param context [GraphQL::Query::Context]
129
+ # @param authorized_result [Boolean]
130
+ # @return [void]
131
+ def end_authorized(type, object, context, authorized_result)
132
+ end
133
+
66
134
  def authorized_lazy(query:, type:, object:)
67
135
  yield
68
136
  end
@@ -74,6 +142,62 @@ module GraphQL
74
142
  def resolve_type_lazy(query:, type:, object:)
75
143
  yield
76
144
  end
145
+
146
+ # A call to `.resolve_type` is starting
147
+ # @param type [Class<GraphQL::Schema::Union>, Module<GraphQL::Schema::Interface>]
148
+ # @param value [Object]
149
+ # @param context [GraphQL::Query::Context]
150
+ # @return [void]
151
+ def begin_resolve_type(type, value, context)
152
+ end
153
+
154
+ # A call to `.resolve_type` just ended
155
+ # @param type [Class<GraphQL::Schema::Union>, Module<GraphQL::Schema::Interface>]
156
+ # @param value [Object]
157
+ # @param context [GraphQL::Query::Context]
158
+ # @param resolved_type [Class<GraphQL::Schema::Object>]
159
+ # @return [void]
160
+ def end_resolve_type(type, value, context, resolved_type)
161
+ end
162
+
163
+ # A dataloader run is starting
164
+ # @param dataloader [GraphQL::Dataloader]
165
+ # @return [void]
166
+ def begin_dataloader(dataloader); end
167
+ # A dataloader run has ended
168
+ # @param dataloder [GraphQL::Dataloader]
169
+ # @return [void]
170
+ def end_dataloader(dataloader); end
171
+
172
+ # A source with pending keys is about to fetch
173
+ # @param source [GraphQL::Dataloader::Source]
174
+ # @return [void]
175
+ def begin_dataloader_source(source); end
176
+ # A fetch call has just ended
177
+ # @param source [GraphQL::Dataloader::Source]
178
+ # @return [void]
179
+ def end_dataloader_source(source); end
180
+
181
+ # Called when Dataloader spins up a new fiber for GraphQL execution
182
+ # @param jobs [Array<#call>] Execution steps to run
183
+ # @return [void]
184
+ def dataloader_spawn_execution_fiber(jobs); end
185
+ # Called when Dataloader spins up a new fiber for fetching data
186
+ # @param pending_sources [GraphQL::Dataloader::Source] Instances with pending keys
187
+ # @return [void]
188
+ def dataloader_spawn_source_fiber(pending_sources); end
189
+ # Called when an execution or source fiber terminates
190
+ # @return [void]
191
+ def dataloader_fiber_exit; end
192
+
193
+ # Called when a Dataloader fiber is paused to wait for data
194
+ # @param source [GraphQL::Dataloader::Source] The Source whose `load` call initiated this `yield`
195
+ # @return [void]
196
+ def dataloader_fiber_yield(source); end
197
+ # Called when a Dataloader fiber is resumed because data has been loaded
198
+ # @param source [GraphQL::Dataloader::Source] The Source whose `load` call previously caused this Fiber to wait
199
+ # @return [void]
200
+ def dataloader_fiber_resume(source); end
77
201
  end
78
202
  end
79
203
  end
@@ -31,6 +31,7 @@ module GraphQL
31
31
  autoload :ScoutTrace, "graphql/tracing/scout_trace"
32
32
  autoload :StatsdTrace, "graphql/tracing/statsd_trace"
33
33
  autoload :PrometheusTrace, "graphql/tracing/prometheus_trace"
34
+ autoload :PerfettoTrace, "graphql/tracing/perfetto_trace"
34
35
 
35
36
  # Objects may include traceable to gain a `.trace(...)` method.
36
37
  # The object must have a `@tracers` ivar of type `Array<<#trace(k, d, &b)>>`.
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module GraphQL
3
- VERSION = "2.4.8"
3
+ VERSION = "2.4.10"
4
4
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.8
4
+ version: 2.4.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Mosolgo
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-12-10 00:00:00.000000000 Z
10
+ date: 2025-02-18 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: base64
@@ -38,6 +37,20 @@ dependencies:
38
37
  - - ">="
39
38
  - !ruby/object:Gem::Version
40
39
  version: '0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: logger
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
41
54
  - !ruby/object:Gem::Dependency
42
55
  name: benchmark-ips
43
56
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +79,20 @@ dependencies:
66
79
  - - "~>"
67
80
  - !ruby/object:Gem::Version
68
81
  version: '1.0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: google-protobuf
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
69
96
  - !ruby/object:Gem::Dependency
70
97
  name: graphql-batch
71
98
  requirement: !ruby/object:Gem::Requirement
@@ -178,6 +205,76 @@ dependencies:
178
205
  - - ">="
179
206
  - !ruby/object:Gem::Version
180
207
  version: '0'
208
+ - !ruby/object:Gem::Dependency
209
+ name: simplecov
210
+ requirement: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - ">="
213
+ - !ruby/object:Gem::Version
214
+ version: '0'
215
+ type: :development
216
+ prerelease: false
217
+ version_requirements: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - ">="
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
222
+ - !ruby/object:Gem::Dependency
223
+ name: simplecov-lcov
224
+ requirement: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - ">="
227
+ - !ruby/object:Gem::Version
228
+ version: '0'
229
+ type: :development
230
+ prerelease: false
231
+ version_requirements: !ruby/object:Gem::Requirement
232
+ requirements:
233
+ - - ">="
234
+ - !ruby/object:Gem::Version
235
+ version: '0'
236
+ - !ruby/object:Gem::Dependency
237
+ name: undercover
238
+ requirement: !ruby/object:Gem::Requirement
239
+ requirements:
240
+ - - ">="
241
+ - !ruby/object:Gem::Version
242
+ version: '0'
243
+ type: :development
244
+ prerelease: false
245
+ version_requirements: !ruby/object:Gem::Requirement
246
+ requirements:
247
+ - - ">="
248
+ - !ruby/object:Gem::Version
249
+ version: '0'
250
+ - !ruby/object:Gem::Dependency
251
+ name: pronto
252
+ requirement: !ruby/object:Gem::Requirement
253
+ requirements:
254
+ - - ">="
255
+ - !ruby/object:Gem::Version
256
+ version: '0'
257
+ type: :development
258
+ prerelease: false
259
+ version_requirements: !ruby/object:Gem::Requirement
260
+ requirements:
261
+ - - ">="
262
+ - !ruby/object:Gem::Version
263
+ version: '0'
264
+ - !ruby/object:Gem::Dependency
265
+ name: pronto-undercover
266
+ requirement: !ruby/object:Gem::Requirement
267
+ requirements:
268
+ - - ">="
269
+ - !ruby/object:Gem::Version
270
+ version: '0'
271
+ type: :development
272
+ prerelease: false
273
+ version_requirements: !ruby/object:Gem::Requirement
274
+ requirements:
275
+ - - ">="
276
+ - !ruby/object:Gem::Version
277
+ version: '0'
181
278
  - !ruby/object:Gem::Dependency
182
279
  name: jekyll
183
280
  requirement: !ruby/object:Gem::Requirement
@@ -192,6 +289,20 @@ dependencies:
192
289
  - - ">="
193
290
  - !ruby/object:Gem::Version
194
291
  version: '0'
292
+ - !ruby/object:Gem::Dependency
293
+ name: jekyll-sass-converter
294
+ requirement: !ruby/object:Gem::Requirement
295
+ requirements:
296
+ - - "~>"
297
+ - !ruby/object:Gem::Version
298
+ version: '2.2'
299
+ type: :development
300
+ prerelease: false
301
+ version_requirements: !ruby/object:Gem::Requirement
302
+ requirements:
303
+ - - "~>"
304
+ - !ruby/object:Gem::Version
305
+ version: '2.2'
195
306
  - !ruby/object:Gem::Dependency
196
307
  name: yard
197
308
  requirement: !ruby/object:Gem::Requirement
@@ -248,6 +359,20 @@ dependencies:
248
359
  - - "~>"
249
360
  - !ruby/object:Gem::Version
250
361
  version: 1.5.0
362
+ - !ruby/object:Gem::Dependency
363
+ name: mutex_m
364
+ requirement: !ruby/object:Gem::Requirement
365
+ requirements:
366
+ - - ">="
367
+ - !ruby/object:Gem::Version
368
+ version: '0'
369
+ type: :development
370
+ prerelease: false
371
+ version_requirements: !ruby/object:Gem::Requirement
372
+ requirements:
373
+ - - ">="
374
+ - !ruby/object:Gem::Version
375
+ version: '0'
251
376
  - !ruby/object:Gem::Dependency
252
377
  name: webrick
253
378
  requirement: !ruby/object:Gem::Requirement
@@ -330,14 +455,13 @@ files:
330
455
  - lib/graphql/analysis_error.rb
331
456
  - lib/graphql/autoload.rb
332
457
  - lib/graphql/backtrace.rb
333
- - lib/graphql/backtrace/inspect_result.rb
334
458
  - lib/graphql/backtrace/table.rb
335
- - lib/graphql/backtrace/trace.rb
336
459
  - lib/graphql/backtrace/traced_error.rb
337
- - lib/graphql/backtrace/tracer.rb
338
460
  - lib/graphql/coercion_error.rb
339
461
  - lib/graphql/current.rb
340
462
  - lib/graphql/dataloader.rb
463
+ - lib/graphql/dataloader/active_record_association_source.rb
464
+ - lib/graphql/dataloader/active_record_source.rb
341
465
  - lib/graphql/dataloader/async_dataloader.rb
342
466
  - lib/graphql/dataloader/null_dataloader.rb
343
467
  - lib/graphql/dataloader/request.rb
@@ -466,6 +590,7 @@ files:
466
590
  - lib/graphql/schema/member/graphql_type_names.rb
467
591
  - lib/graphql/schema/member/has_arguments.rb
468
592
  - lib/graphql/schema/member/has_ast_node.rb
593
+ - lib/graphql/schema/member/has_dataloader.rb
469
594
  - lib/graphql/schema/member/has_deprecation_reason.rb
470
595
  - lib/graphql/schema/member/has_directives.rb
471
596
  - lib/graphql/schema/member/has_fields.rb
@@ -479,7 +604,6 @@ files:
479
604
  - lib/graphql/schema/member/validates_input.rb
480
605
  - lib/graphql/schema/mutation.rb
481
606
  - lib/graphql/schema/non_null.rb
482
- - lib/graphql/schema/null_mask.rb
483
607
  - lib/graphql/schema/object.rb
484
608
  - lib/graphql/schema/printer.rb
485
609
  - lib/graphql/schema/relay_classic_mutation.rb
@@ -604,6 +728,9 @@ files:
604
728
  - lib/graphql/tracing/notifications_trace.rb
605
729
  - lib/graphql/tracing/notifications_tracing.rb
606
730
  - lib/graphql/tracing/null_trace.rb
731
+ - lib/graphql/tracing/perfetto_trace.rb
732
+ - lib/graphql/tracing/perfetto_trace/trace.proto
733
+ - lib/graphql/tracing/perfetto_trace/trace_pb.rb
607
734
  - lib/graphql/tracing/platform_trace.rb
608
735
  - lib/graphql/tracing/platform_tracing.rb
609
736
  - lib/graphql/tracing/prometheus_trace.rb
@@ -654,7 +781,6 @@ metadata:
654
781
  bug_tracker_uri: https://github.com/rmosolgo/graphql-ruby/issues
655
782
  mailing_list_uri: https://buttondown.email/graphql-ruby
656
783
  rubygems_mfa_required: 'true'
657
- post_install_message:
658
784
  rdoc_options: []
659
785
  require_paths:
660
786
  - lib
@@ -669,8 +795,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
669
795
  - !ruby/object:Gem::Version
670
796
  version: '0'
671
797
  requirements: []
672
- rubygems_version: 3.5.12
673
- signing_key:
798
+ rubygems_version: 3.6.3
674
799
  specification_version: 4
675
800
  summary: A GraphQL language and runtime for Ruby
676
801
  test_files: []
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
- module GraphQL
3
- class Backtrace
4
- module InspectResult
5
- module_function
6
-
7
- def inspect_result(obj)
8
- case obj
9
- when Hash
10
- "{" +
11
- obj.map do |key, val|
12
- "#{key}: #{inspect_truncated(val)}"
13
- end.join(", ") +
14
- "}"
15
- when Array
16
- "[" +
17
- obj.map { |v| inspect_truncated(v) }.join(", ") +
18
- "]"
19
- else
20
- inspect_truncated(obj)
21
- end
22
- end
23
-
24
- def inspect_truncated(obj)
25
- case obj
26
- when Hash
27
- "{...}"
28
- when Array
29
- "[...]"
30
- when GraphQL::Execution::Lazy
31
- "(unresolved)"
32
- else
33
- "#{obj.inspect}"
34
- end
35
- end
36
- end
37
- end
38
- end
@@ -1,93 +0,0 @@
1
- # frozen_string_literal: true
2
- module GraphQL
3
- class Backtrace
4
- module Trace
5
- def initialize(*args, **kwargs, &block)
6
- @__backtrace_contexts = {}
7
- @__backtrace_last_context = nil
8
- super
9
- end
10
-
11
- def validate(query:, validate:)
12
- if query.multiplex
13
- push_query_backtrace_context(query)
14
- end
15
- super
16
- end
17
-
18
- def analyze_query(query:)
19
- if query.multiplex # missing for stand-alone static validation
20
- push_query_backtrace_context(query)
21
- end
22
- super
23
- end
24
-
25
- def execute_query(query:)
26
- push_query_backtrace_context(query)
27
- super
28
- end
29
-
30
- def execute_query_lazy(query:, multiplex:)
31
- query ||= multiplex.queries.first
32
- push_query_backtrace_context(query)
33
- super
34
- end
35
-
36
- def execute_field(field:, query:, ast_node:, arguments:, object:)
37
- push_field_backtrace_context(field, query, ast_node, arguments, object)
38
- super
39
- end
40
-
41
- def execute_field_lazy(field:, query:, ast_node:, arguments:, object:)
42
- push_field_backtrace_context(field, query, ast_node, arguments, object)
43
- super
44
- end
45
-
46
- def execute_multiplex(multiplex:)
47
- super
48
- rescue StandardError => err
49
- # This is an unhandled error from execution,
50
- # Re-raise it with a GraphQL trace.
51
- potential_context = @__backtrace_last_context
52
- if potential_context.is_a?(GraphQL::Query::Context) ||
53
- potential_context.is_a?(Backtrace::Frame)
54
- raise TracedError.new(err, potential_context)
55
- else
56
- raise
57
- end
58
- end
59
-
60
- private
61
-
62
- def push_query_backtrace_context(query)
63
- push_data = query
64
- push_key = []
65
- @__backtrace_contexts[push_key] = push_data
66
- @__backtrace_last_context = push_data
67
- end
68
-
69
- def push_field_backtrace_context(field, query, ast_node, arguments, object)
70
- push_key = query.context[:current_path]
71
- push_storage = @__backtrace_contexts
72
- parent_frame = push_storage[push_key[0..-2]]
73
-
74
- if parent_frame.is_a?(GraphQL::Query)
75
- parent_frame = parent_frame.context
76
- end
77
-
78
- push_data = Frame.new(
79
- query: query,
80
- path: push_key,
81
- ast_node: ast_node,
82
- field: field,
83
- object: object,
84
- arguments: arguments,
85
- parent_frame: parent_frame,
86
- )
87
- push_storage[push_key] = push_data
88
- @__backtrace_last_context = push_data
89
- end
90
-
91
- end
92
- end
93
- end
@@ -1,80 +0,0 @@
1
- # frozen_string_literal: true
2
- module GraphQL
3
- class Backtrace
4
- # TODO this is not fiber-friendly
5
- module Tracer
6
- module_function
7
-
8
- # Implement the {GraphQL::Tracing} API.
9
- def trace(key, metadata)
10
- case key
11
- when "lex", "parse"
12
- # No context here, don't have a query yet
13
- nil
14
- when "execute_multiplex", "analyze_multiplex"
15
- # No query context yet
16
- nil
17
- when "validate", "analyze_query", "execute_query", "execute_query_lazy"
18
- push_key = []
19
- if (query = metadata[:query]) || ((queries = metadata[:queries]) && (query = queries.first))
20
- push_data = query
21
- multiplex = query.multiplex
22
- elsif (multiplex = metadata[:multiplex])
23
- push_data = multiplex.queries.first
24
- end
25
- when "execute_field", "execute_field_lazy"
26
- query = metadata[:query]
27
- multiplex = query.multiplex
28
- push_key = query.context[:current_path]
29
- parent_frame = multiplex.context[:graphql_backtrace_contexts][push_key[0..-2]]
30
-
31
- if parent_frame.is_a?(GraphQL::Query)
32
- parent_frame = parent_frame.context
33
- end
34
-
35
- push_data = Frame.new(
36
- query: query,
37
- path: push_key,
38
- ast_node: metadata[:ast_node],
39
- field: metadata[:field],
40
- object: metadata[:object],
41
- arguments: metadata[:arguments],
42
- parent_frame: parent_frame,
43
- )
44
- else
45
- # Custom key, no backtrace data for this
46
- nil
47
- end
48
-
49
- if push_data && multiplex
50
- push_storage = multiplex.context[:graphql_backtrace_contexts] ||= {}
51
- push_storage[push_key] = push_data
52
- multiplex.context[:last_graphql_backtrace_context] = push_data
53
- end
54
-
55
- if key == "execute_multiplex"
56
- multiplex_context = metadata[:multiplex].context
57
- begin
58
- yield
59
- rescue StandardError => err
60
- # This is an unhandled error from execution,
61
- # Re-raise it with a GraphQL trace.
62
- potential_context = multiplex_context[:last_graphql_backtrace_context]
63
-
64
- if potential_context.is_a?(GraphQL::Query::Context) ||
65
- potential_context.is_a?(Backtrace::Frame)
66
- raise TracedError.new(err, potential_context)
67
- else
68
- raise
69
- end
70
- ensure
71
- multiplex_context.delete(:graphql_backtrace_contexts)
72
- multiplex_context.delete(:last_graphql_backtrace_context)
73
- end
74
- else
75
- yield
76
- end
77
- end
78
- end
79
- end
80
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
- module GraphQL
3
- class Schema
4
- # @api private
5
- module NullMask
6
- def self.call(member, ctx)
7
- false
8
- end
9
- end
10
- end
11
- end