graphql 2.3.7 → 2.4.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/install_generator.rb +46 -0
  3. data/lib/generators/graphql/orm_mutations_base.rb +1 -1
  4. data/lib/generators/graphql/templates/base_resolver.erb +2 -0
  5. data/lib/generators/graphql/type_generator.rb +1 -1
  6. data/lib/graphql/analysis/field_usage.rb +1 -1
  7. data/lib/graphql/analysis/query_complexity.rb +3 -3
  8. data/lib/graphql/analysis/visitor.rb +8 -7
  9. data/lib/graphql/analysis.rb +4 -4
  10. data/lib/graphql/autoload.rb +38 -0
  11. data/lib/graphql/current.rb +52 -0
  12. data/lib/graphql/dataloader/async_dataloader.rb +7 -6
  13. data/lib/graphql/dataloader/source.rb +7 -4
  14. data/lib/graphql/dataloader.rb +40 -19
  15. data/lib/graphql/execution/interpreter/arguments_cache.rb +5 -10
  16. data/lib/graphql/execution/interpreter/resolve.rb +13 -9
  17. data/lib/graphql/execution/interpreter/runtime.rb +35 -31
  18. data/lib/graphql/execution/interpreter.rb +9 -5
  19. data/lib/graphql/execution/lookahead.rb +18 -11
  20. data/lib/graphql/introspection/directive_type.rb +1 -1
  21. data/lib/graphql/introspection/entry_points.rb +2 -2
  22. data/lib/graphql/introspection/field_type.rb +1 -1
  23. data/lib/graphql/introspection/schema_type.rb +6 -11
  24. data/lib/graphql/introspection/type_type.rb +5 -5
  25. data/lib/graphql/invalid_null_error.rb +1 -1
  26. data/lib/graphql/language/cache.rb +13 -0
  27. data/lib/graphql/language/comment.rb +18 -0
  28. data/lib/graphql/language/document_from_schema_definition.rb +62 -34
  29. data/lib/graphql/language/lexer.rb +18 -15
  30. data/lib/graphql/language/nodes.rb +24 -16
  31. data/lib/graphql/language/parser.rb +14 -1
  32. data/lib/graphql/language/printer.rb +31 -15
  33. data/lib/graphql/language/sanitized_printer.rb +1 -1
  34. data/lib/graphql/language.rb +6 -6
  35. data/lib/graphql/pagination/connection.rb +1 -1
  36. data/lib/graphql/query/context/scoped_context.rb +1 -1
  37. data/lib/graphql/query/context.rb +13 -6
  38. data/lib/graphql/query/null_context.rb +3 -5
  39. data/lib/graphql/query/variable_validation_error.rb +1 -1
  40. data/lib/graphql/query.rb +72 -18
  41. data/lib/graphql/railtie.rb +7 -0
  42. data/lib/graphql/rubocop/graphql/field_type_in_block.rb +144 -0
  43. data/lib/graphql/rubocop/graphql/root_types_in_block.rb +38 -0
  44. data/lib/graphql/rubocop.rb +2 -0
  45. data/lib/graphql/schema/addition.rb +2 -1
  46. data/lib/graphql/schema/always_visible.rb +6 -2
  47. data/lib/graphql/schema/argument.rb +14 -1
  48. data/lib/graphql/schema/build_from_definition.rb +9 -1
  49. data/lib/graphql/schema/directive/flagged.rb +2 -2
  50. data/lib/graphql/schema/directive.rb +1 -1
  51. data/lib/graphql/schema/enum.rb +71 -23
  52. data/lib/graphql/schema/enum_value.rb +10 -2
  53. data/lib/graphql/schema/field/connection_extension.rb +1 -1
  54. data/lib/graphql/schema/field/scope_extension.rb +1 -1
  55. data/lib/graphql/schema/field.rb +102 -47
  56. data/lib/graphql/schema/field_extension.rb +1 -1
  57. data/lib/graphql/schema/has_single_input_argument.rb +5 -2
  58. data/lib/graphql/schema/input_object.rb +90 -39
  59. data/lib/graphql/schema/interface.rb +22 -5
  60. data/lib/graphql/schema/introspection_system.rb +5 -16
  61. data/lib/graphql/schema/loader.rb +1 -1
  62. data/lib/graphql/schema/member/base_dsl_methods.rb +15 -0
  63. data/lib/graphql/schema/member/has_arguments.rb +36 -23
  64. data/lib/graphql/schema/member/has_directives.rb +3 -3
  65. data/lib/graphql/schema/member/has_fields.rb +26 -6
  66. data/lib/graphql/schema/member/has_interfaces.rb +4 -4
  67. data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
  68. data/lib/graphql/schema/member/has_validators.rb +1 -1
  69. data/lib/graphql/schema/object.rb +8 -0
  70. data/lib/graphql/schema/printer.rb +1 -0
  71. data/lib/graphql/schema/relay_classic_mutation.rb +0 -1
  72. data/lib/graphql/schema/resolver.rb +12 -14
  73. data/lib/graphql/schema/subscription.rb +52 -6
  74. data/lib/graphql/schema/type_expression.rb +2 -2
  75. data/lib/graphql/schema/union.rb +1 -1
  76. data/lib/graphql/schema/validator/all_validator.rb +62 -0
  77. data/lib/graphql/schema/validator/required_validator.rb +28 -4
  78. data/lib/graphql/schema/validator.rb +3 -1
  79. data/lib/graphql/schema/visibility/migration.rb +188 -0
  80. data/lib/graphql/schema/visibility/profile.rb +359 -0
  81. data/lib/graphql/schema/visibility/visit.rb +190 -0
  82. data/lib/graphql/schema/visibility.rb +294 -0
  83. data/lib/graphql/schema/warden.rb +179 -16
  84. data/lib/graphql/schema.rb +348 -94
  85. data/lib/graphql/static_validation/base_visitor.rb +6 -5
  86. data/lib/graphql/static_validation/literal_validator.rb +4 -4
  87. data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
  88. data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +1 -1
  89. data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -2
  90. data/lib/graphql/static_validation/rules/directives_are_defined.rb +3 -3
  91. data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -0
  92. data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +12 -2
  93. data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +2 -2
  94. data/lib/graphql/static_validation/rules/fields_will_merge.rb +8 -7
  95. data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
  96. data/lib/graphql/static_validation/rules/fragment_types_exist.rb +12 -2
  97. data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
  98. data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
  99. data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +1 -1
  100. data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
  101. data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +4 -4
  102. data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +3 -3
  103. data/lib/graphql/static_validation/rules/subscription_root_exists.rb +1 -1
  104. data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +1 -1
  105. data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
  106. data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +1 -1
  107. data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +2 -2
  108. data/lib/graphql/static_validation/rules/variables_are_input_types.rb +11 -2
  109. data/lib/graphql/static_validation/validation_context.rb +18 -2
  110. data/lib/graphql/subscriptions/action_cable_subscriptions.rb +3 -2
  111. data/lib/graphql/subscriptions/broadcast_analyzer.rb +10 -4
  112. data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +12 -10
  113. data/lib/graphql/subscriptions/event.rb +13 -2
  114. data/lib/graphql/subscriptions/serialize.rb +2 -0
  115. data/lib/graphql/subscriptions.rb +6 -4
  116. data/lib/graphql/testing/helpers.rb +10 -6
  117. data/lib/graphql/tracing/active_support_notifications_trace.rb +1 -1
  118. data/lib/graphql/tracing/active_support_notifications_tracing.rb +1 -1
  119. data/lib/graphql/tracing/appoptics_trace.rb +2 -0
  120. data/lib/graphql/tracing/appoptics_tracing.rb +2 -0
  121. data/lib/graphql/tracing/appsignal_trace.rb +2 -0
  122. data/lib/graphql/tracing/appsignal_tracing.rb +2 -0
  123. data/lib/graphql/tracing/call_legacy_tracers.rb +66 -0
  124. data/lib/graphql/tracing/data_dog_trace.rb +2 -0
  125. data/lib/graphql/tracing/data_dog_tracing.rb +2 -0
  126. data/lib/graphql/tracing/legacy_hooks_trace.rb +1 -0
  127. data/lib/graphql/tracing/legacy_trace.rb +4 -61
  128. data/lib/graphql/tracing/new_relic_trace.rb +2 -0
  129. data/lib/graphql/tracing/new_relic_tracing.rb +2 -0
  130. data/lib/graphql/tracing/notifications_trace.rb +2 -2
  131. data/lib/graphql/tracing/notifications_tracing.rb +2 -0
  132. data/lib/graphql/tracing/null_trace.rb +9 -0
  133. data/lib/graphql/tracing/prometheus_trace/graphql_collector.rb +2 -0
  134. data/lib/graphql/tracing/prometheus_trace.rb +5 -0
  135. data/lib/graphql/tracing/prometheus_tracing.rb +2 -0
  136. data/lib/graphql/tracing/scout_trace.rb +2 -0
  137. data/lib/graphql/tracing/scout_tracing.rb +2 -0
  138. data/lib/graphql/tracing/sentry_trace.rb +2 -0
  139. data/lib/graphql/tracing/statsd_trace.rb +2 -0
  140. data/lib/graphql/tracing/statsd_tracing.rb +2 -0
  141. data/lib/graphql/tracing/trace.rb +3 -0
  142. data/lib/graphql/tracing.rb +28 -30
  143. data/lib/graphql/types/relay/connection_behaviors.rb +12 -2
  144. data/lib/graphql/types/relay/edge_behaviors.rb +11 -1
  145. data/lib/graphql/types/relay/page_info_behaviors.rb +4 -0
  146. data/lib/graphql/types.rb +18 -11
  147. data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
  148. data/lib/graphql/version.rb +1 -1
  149. data/lib/graphql.rb +53 -45
  150. metadata +33 -8
  151. data/lib/graphql/language/token.rb +0 -34
  152. data/lib/graphql/schema/invalid_type_error.rb +0 -7
@@ -20,12 +20,22 @@ module GraphQL
20
20
  def after_resolve(value:, context:, object:, arguments:, **rest)
21
21
  if value.is_a?(GraphQL::ExecutionError)
22
22
  value
23
+ elsif @field.resolver&.method_defined?(:subscription_written?) &&
24
+ (subscription_namespace = context.namespace(:subscriptions)) &&
25
+ (subscriptions_by_path = subscription_namespace[:subscriptions])
26
+ (subscription_instance = subscriptions_by_path[context.current_path])
27
+ # If it was already written, don't append this event to be written later
28
+ if !subscription_instance.subscription_written?
29
+ events = context.namespace(:subscriptions)[:events]
30
+ events << subscription_instance.event
31
+ end
32
+ value
23
33
  elsif (events = context.namespace(:subscriptions)[:events])
24
34
  # This is the first execution, so gather an Event
25
35
  # for the backend to register:
26
36
  event = Subscriptions::Event.new(
27
37
  name: field.name,
28
- arguments: arguments_without_field_extras(arguments: arguments),
38
+ arguments: arguments,
29
39
  context: context,
30
40
  field: field,
31
41
  )
@@ -33,7 +43,7 @@ module GraphQL
33
43
  value
34
44
  elsif context.query.subscription_topic == Subscriptions::Event.serialize(
35
45
  field.name,
36
- arguments_without_field_extras(arguments: arguments),
46
+ arguments,
37
47
  field,
38
48
  scope: (field.subscription_scope ? context[field.subscription_scope] : nil),
39
49
  )
@@ -45,14 +55,6 @@ module GraphQL
45
55
  context.skip
46
56
  end
47
57
  end
48
-
49
- private
50
-
51
- def arguments_without_field_extras(arguments:)
52
- arguments.dup.tap do |event_args|
53
- field.extras.each { |k| event_args.delete(k) }
54
- end
55
- end
56
58
  end
57
59
  end
58
60
  end
@@ -20,7 +20,7 @@ module GraphQL
20
20
 
21
21
  def initialize(name:, arguments:, field: nil, context: nil, scope: nil)
22
22
  @name = name
23
- @arguments = arguments
23
+ @arguments = self.class.arguments_without_field_extras(arguments: arguments, field: field)
24
24
  @context = context
25
25
  field ||= context.field
26
26
  scope_key = field.subscription_scope
@@ -39,6 +39,7 @@ module GraphQL
39
39
  # @return [String] an identifier for this unit of subscription
40
40
  def self.serialize(_name, arguments, field, scope:, context: GraphQL::Query::NullContext.instance)
41
41
  subscription = field.resolver || GraphQL::Schema::Subscription
42
+ arguments = arguments_without_field_extras(field: field, arguments: arguments)
42
43
  normalized_args = stringify_args(field, arguments.to_h, context)
43
44
  subscription.topic_for(arguments: normalized_args, field: field, scope: scope)
44
45
  end
@@ -60,6 +61,16 @@ module GraphQL
60
61
  end
61
62
 
62
63
  class << self
64
+ def arguments_without_field_extras(arguments:, field:)
65
+ if !field.extras.empty?
66
+ arguments = arguments.dup
67
+ field.extras.each do |extra_key|
68
+ arguments.delete(extra_key)
69
+ end
70
+ end
71
+ arguments
72
+ end
73
+
63
74
  private
64
75
 
65
76
  # This method does not support cyclic references in the Hash,
@@ -137,7 +148,7 @@ module GraphQL
137
148
  end
138
149
 
139
150
  def get_arg_definition(arg_owner, arg_name, context)
140
- arg_owner.get_argument(arg_name, context) || arg_owner.arguments(context).each_value.find { |v| v.keyword.to_s == arg_name }
151
+ context.types.argument(arg_owner, arg_name) || context.types.arguments(arg_owner).find { |v| v.keyword.to_s == arg_name }
141
152
  end
142
153
  end
143
154
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  require "set"
3
+ require "ostruct"
4
+
3
5
  module GraphQL
4
6
  class Subscriptions
5
7
  # Serialization helpers for passing subscription data around.
@@ -64,12 +64,12 @@ module GraphQL
64
64
  event_name = event_name.to_s
65
65
 
66
66
  # Try with the verbatim input first:
67
- field = @schema.get_field(@schema.subscription, event_name, context)
67
+ field = dummy_query.types.field(@schema.subscription, event_name) # rubocop:disable Development/ContextIsPassedCop
68
68
 
69
69
  if field.nil?
70
70
  # And if it wasn't found, normalize it:
71
71
  normalized_event_name = normalize_name(event_name)
72
- field = @schema.get_field(@schema.subscription, normalized_event_name, context)
72
+ field = dummy_query.types.field(@schema.subscription, normalized_event_name) # rubocop:disable Development/ContextIsPassedCop
73
73
  if field.nil?
74
74
  raise InvalidTriggerError, "No subscription matching trigger: #{event_name} (looked for #{@schema.subscription.graphql_name}.#{normalized_event_name})"
75
75
  end
@@ -250,6 +250,8 @@ module GraphQL
250
250
  def normalize_arguments(event_name, arg_owner, args, context)
251
251
  case arg_owner
252
252
  when GraphQL::Schema::Field, Class
253
+ return args if args.nil?
254
+
253
255
  if arg_owner.is_a?(Class) && !arg_owner.kind.input_object?
254
256
  # it's a type, but not an input object
255
257
  return args
@@ -289,7 +291,7 @@ module GraphQL
289
291
  end
290
292
  end
291
293
 
292
- if missing_arg_names.any?
294
+ if !missing_arg_names.empty?
293
295
  arg_owner_name = if arg_owner.is_a?(GraphQL::Schema::Field)
294
296
  arg_owner.path
295
297
  elsif arg_owner.is_a?(Class)
@@ -302,7 +304,7 @@ module GraphQL
302
304
 
303
305
  normalized_args
304
306
  when GraphQL::Schema::List
305
- args.map { |a| normalize_arguments(event_name, arg_owner.of_type, a, context) }
307
+ args&.map { |a| normalize_arguments(event_name, arg_owner.of_type, a, context) }
306
308
  when GraphQL::Schema::NonNull
307
309
  normalize_arguments(event_name, arg_owner.of_type, args, context)
308
310
  else
@@ -43,7 +43,7 @@ module GraphQL
43
43
  type_name, *field_names = field_path.split(".")
44
44
  dummy_query = GraphQL::Query.new(schema, "{ __typename }", context: context)
45
45
  query_context = dummy_query.context
46
- object_type = dummy_query.get_type(type_name) # rubocop:disable Development/ContextIsPassedCop
46
+ object_type = dummy_query.types.type(type_name) # rubocop:disable Development/ContextIsPassedCop
47
47
  if object_type
48
48
  graphql_result = object
49
49
  field_names.each do |field_name|
@@ -52,12 +52,13 @@ module GraphQL
52
52
  if graphql_result.nil?
53
53
  return nil
54
54
  end
55
- visible_field = dummy_query.get_field(object_type, field_name)
55
+ visible_field = dummy_query.types.field(object_type, field_name) # rubocop:disable Development/ContextIsPassedCop
56
56
  if visible_field
57
57
  dummy_query.context.dataloader.run_isolated {
58
+ query_context[:current_field] = visible_field
58
59
  field_args = visible_field.coerce_arguments(graphql_result, arguments, query_context)
59
60
  field_args = schema.sync_lazy(field_args)
60
- if visible_field.extras.any?
61
+ if !visible_field.extras.empty?
61
62
  extra_args = {}
62
63
  visible_field.extras.each do |extra|
63
64
  extra_args[extra] = case extra
@@ -90,10 +91,13 @@ module GraphQL
90
91
  end
91
92
  end
92
93
  graphql_result
93
- elsif schema.has_defined_type?(type_name)
94
- raise TypeNotVisibleError.new(type_name: type_name)
95
94
  else
96
- raise TypeNotDefinedError.new(type_name: type_name)
95
+ unfiltered_type = schema.use_visibility_profile? ? schema.visibility.get_type(type_name) : schema.get_type(type_name) # rubocop:disable Development/ContextIsPassedCop
96
+ if unfiltered_type
97
+ raise TypeNotVisibleError.new(type_name: type_name)
98
+ else
99
+ raise TypeNotDefinedError.new(type_name: type_name)
100
+ end
97
101
  end
98
102
  end
99
103
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'graphql/tracing/notifications_trace'
3
+ require "graphql/tracing/notifications_trace"
4
4
 
5
5
  module GraphQL
6
6
  module Tracing
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'graphql/tracing/notifications_tracing'
3
+ require "graphql/tracing/notifications_tracing"
4
4
 
5
5
  module GraphQL
6
6
  module Tracing
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/tracing/platform_trace"
4
+
3
5
  module GraphQL
4
6
  module Tracing
5
7
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/tracing/platform_tracing"
4
+
3
5
  module GraphQL
4
6
  module Tracing
5
7
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/tracing/platform_trace"
4
+
3
5
  module GraphQL
4
6
  module Tracing
5
7
  module AppsignalTrace
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/tracing/platform_tracing"
4
+
3
5
  module GraphQL
4
6
  module Tracing
5
7
  class AppsignalTracing < PlatformTracing
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Tracing
5
+ # This trace class calls legacy-style tracer with payload hashes.
6
+ # New-style `trace_with` modules significantly reduce the overhead of tracing,
7
+ # but that advantage is lost when legacy-style tracers are also used (since the payload hashes are still constructed).
8
+ module CallLegacyTracers
9
+ def lex(query_string:)
10
+ (@multiplex || @query).trace("lex", { query_string: query_string }) { super }
11
+ end
12
+
13
+ def parse(query_string:)
14
+ (@multiplex || @query).trace("parse", { query_string: query_string }) { super }
15
+ end
16
+
17
+ def validate(query:, validate:)
18
+ query.trace("validate", { validate: validate, query: query }) { super }
19
+ end
20
+
21
+ def analyze_multiplex(multiplex:)
22
+ multiplex.trace("analyze_multiplex", { multiplex: multiplex }) { super }
23
+ end
24
+
25
+ def analyze_query(query:)
26
+ query.trace("analyze_query", { query: query }) { super }
27
+ end
28
+
29
+ def execute_multiplex(multiplex:)
30
+ multiplex.trace("execute_multiplex", { multiplex: multiplex }) { super }
31
+ end
32
+
33
+ def execute_query(query:)
34
+ query.trace("execute_query", { query: query }) { super }
35
+ end
36
+
37
+ def execute_query_lazy(query:, multiplex:)
38
+ multiplex.trace("execute_query_lazy", { multiplex: multiplex, query: query }) { super }
39
+ end
40
+
41
+ def execute_field(field:, query:, ast_node:, arguments:, object:)
42
+ query.trace("execute_field", { field: field, query: query, ast_node: ast_node, arguments: arguments, object: object, owner: field.owner, path: query.context[:current_path] }) { super }
43
+ end
44
+
45
+ def execute_field_lazy(field:, query:, ast_node:, arguments:, object:)
46
+ query.trace("execute_field_lazy", { field: field, query: query, ast_node: ast_node, arguments: arguments, object: object, owner: field.owner, path: query.context[:current_path] }) { super }
47
+ end
48
+
49
+ def authorized(query:, type:, object:)
50
+ query.trace("authorized", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super }
51
+ end
52
+
53
+ def authorized_lazy(query:, type:, object:)
54
+ query.trace("authorized_lazy", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super }
55
+ end
56
+
57
+ def resolve_type(query:, type:, object:)
58
+ query.trace("resolve_type", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super }
59
+ end
60
+
61
+ def resolve_type_lazy(query:, type:, object:)
62
+ query.trace("resolve_type_lazy", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super }
63
+ end
64
+ end
65
+ end
66
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/tracing/platform_trace"
4
+
3
5
  module GraphQL
4
6
  module Tracing
5
7
  module DataDogTrace
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/tracing/platform_tracing"
4
+
3
5
  module GraphQL
4
6
  module Tracing
5
7
  class DataDogTracing < PlatformTracing
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module GraphQL
3
4
  module Tracing
4
5
  module LegacyHooksTrace
@@ -1,67 +1,10 @@
1
1
  # frozen_string_literal: true
2
- module GraphQL
3
- module Tracing
4
- # This trace class calls legacy-style tracer with payload hashes.
5
- # New-style `trace_with` modules significantly reduce the overhead of tracing,
6
- # but that advantage is lost when legacy-style tracers are also used (since the payload hashes are still constructed).
7
- module CallLegacyTracers
8
- def lex(query_string:)
9
- (@multiplex || @query).trace("lex", { query_string: query_string }) { super }
10
- end
11
-
12
- def parse(query_string:)
13
- (@multiplex || @query).trace("parse", { query_string: query_string }) { super }
14
- end
15
-
16
- def validate(query:, validate:)
17
- query.trace("validate", { validate: validate, query: query }) { super }
18
- end
19
-
20
- def analyze_multiplex(multiplex:)
21
- multiplex.trace("analyze_multiplex", { multiplex: multiplex }) { super }
22
- end
23
-
24
- def analyze_query(query:)
25
- query.trace("analyze_query", { query: query }) { super }
26
- end
27
-
28
- def execute_multiplex(multiplex:)
29
- multiplex.trace("execute_multiplex", { multiplex: multiplex }) { super }
30
- end
31
-
32
- def execute_query(query:)
33
- query.trace("execute_query", { query: query }) { super }
34
- end
35
-
36
- def execute_query_lazy(query:, multiplex:)
37
- multiplex.trace("execute_query_lazy", { multiplex: multiplex, query: query }) { super }
38
- end
39
2
 
40
- def execute_field(field:, query:, ast_node:, arguments:, object:)
41
- query.trace("execute_field", { field: field, query: query, ast_node: ast_node, arguments: arguments, object: object, owner: field.owner, path: query.context[:current_path] }) { super }
42
- end
43
-
44
- def execute_field_lazy(field:, query:, ast_node:, arguments:, object:)
45
- query.trace("execute_field_lazy", { field: field, query: query, ast_node: ast_node, arguments: arguments, object: object, owner: field.owner, path: query.context[:current_path] }) { super }
46
- end
47
-
48
- def authorized(query:, type:, object:)
49
- query.trace("authorized", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super }
50
- end
51
-
52
- def authorized_lazy(query:, type:, object:)
53
- query.trace("authorized_lazy", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super }
54
- end
55
-
56
- def resolve_type(query:, type:, object:)
57
- query.trace("resolve_type", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super }
58
- end
59
-
60
- def resolve_type_lazy(query:, type:, object:)
61
- query.trace("resolve_type_lazy", { context: query.context, type: type, object: object, path: query.context[:current_path] }) { super }
62
- end
63
- end
3
+ require "graphql/tracing/trace"
4
+ require "graphql/tracing/call_legacy_tracers"
64
5
 
6
+ module GraphQL
7
+ module Tracing
65
8
  class LegacyTrace < Trace
66
9
  include CallLegacyTracers
67
10
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/tracing/platform_trace"
4
+
3
5
  module GraphQL
4
6
  module Tracing
5
7
  module NewRelicTrace
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/tracing/platform_tracing"
4
+
3
5
  module GraphQL
4
6
  module Tracing
5
7
  class NewRelicTracing < PlatformTracing
@@ -33,8 +33,8 @@ module GraphQL
33
33
  "resolve_type_lazy" => "resolve_type.graphql",
34
34
  }.each do |trace_method, platform_key|
35
35
  module_eval <<-RUBY, __FILE__, __LINE__
36
- def #{trace_method}(**metadata, &blk)
37
- @notifications_engine.instrument("#{platform_key}", metadata, &blk)
36
+ def #{trace_method}(**metadata, &block)
37
+ @notifications_engine.instrument("#{platform_key}", metadata) { super(**metadata, &block) }
38
38
  end
39
39
  RUBY
40
40
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/tracing/platform_tracing"
4
+
3
5
  module GraphQL
4
6
  module Tracing
5
7
  # This implementation forwards events to a notification handler (i.e.
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "graphql/tracing/trace"
4
+
5
+ module GraphQL
6
+ module Tracing
7
+ NullTrace = Trace.new
8
+ end
9
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/tracing"
4
+
3
5
  module GraphQL
4
6
  module Tracing
5
7
  module PrometheusTrace
@@ -1,8 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/tracing/platform_trace"
4
+
3
5
  module GraphQL
4
6
  module Tracing
5
7
  module PrometheusTrace
8
+ if defined?(PrometheusExporter::Server)
9
+ autoload :GraphQLCollector, "graphql/tracing/prometheus_trace/graphql_collector"
10
+ end
6
11
  include PlatformTrace
7
12
 
8
13
  def initialize(client: PrometheusExporter::Client.default, keys_whitelist: ["execute_field", "execute_field_lazy"], collector_type: "graphql", **rest)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/tracing/platform_tracing"
4
+
3
5
  module GraphQL
4
6
  module Tracing
5
7
  class PrometheusTracing < PlatformTracing
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/tracing/platform_trace"
4
+
3
5
  module GraphQL
4
6
  module Tracing
5
7
  module ScoutTrace
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/tracing/platform_tracing"
4
+
3
5
  module GraphQL
4
6
  module Tracing
5
7
  class ScoutTracing < PlatformTracing
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/tracing/platform_trace"
4
+
3
5
  module GraphQL
4
6
  module Tracing
5
7
  module SentryTrace
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/tracing/platform_trace"
4
+
3
5
  module GraphQL
4
6
  module Tracing
5
7
  module StatsdTrace
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "graphql/tracing/platform_tracing"
4
+
3
5
  module GraphQL
4
6
  module Tracing
5
7
  class StatsdTracing < PlatformTracing
@@ -1,4 +1,7 @@
1
1
  # frozen_string_literal: true
2
+
3
+ require "graphql/tracing"
4
+
2
5
  module GraphQL
3
6
  module Tracing
4
7
  # This is the base class for a `trace` instance whose methods are called during query execution.
@@ -1,38 +1,36 @@
1
1
  # frozen_string_literal: true
2
- require "graphql/tracing/trace"
3
- require "graphql/tracing/legacy_trace"
4
- require "graphql/tracing/legacy_hooks_trace"
5
2
 
6
- # Legacy tracing:
7
- require "graphql/tracing/active_support_notifications_tracing"
8
- require "graphql/tracing/platform_tracing"
9
- require "graphql/tracing/appoptics_tracing"
10
- require "graphql/tracing/appsignal_tracing"
11
- require "graphql/tracing/data_dog_tracing"
12
- require "graphql/tracing/new_relic_tracing"
13
- require "graphql/tracing/scout_tracing"
14
- require "graphql/tracing/statsd_tracing"
15
- require "graphql/tracing/prometheus_tracing"
16
-
17
- # New Tracing:
18
- require "graphql/tracing/active_support_notifications_trace"
19
- require "graphql/tracing/platform_trace"
20
- require "graphql/tracing/appoptics_trace"
21
- require "graphql/tracing/appsignal_trace"
22
- require "graphql/tracing/data_dog_trace"
23
- require "graphql/tracing/new_relic_trace"
24
- require "graphql/tracing/notifications_trace"
25
- require "graphql/tracing/sentry_trace"
26
- require "graphql/tracing/scout_trace"
27
- require "graphql/tracing/statsd_trace"
28
- require "graphql/tracing/prometheus_trace"
29
- if defined?(PrometheusExporter::Server)
30
- require "graphql/tracing/prometheus_trace/graphql_collector"
31
- end
32
3
 
33
4
  module GraphQL
34
5
  module Tracing
35
- NullTrace = Trace.new
6
+ autoload :Trace, "graphql/tracing/trace"
7
+ autoload :CallLegacyTracers, "graphql/tracing/call_legacy_tracers"
8
+ autoload :LegacyTrace, "graphql/tracing/legacy_trace"
9
+ autoload :LegacyHooksTrace, "graphql/tracing/legacy_hooks_trace"
10
+ autoload :NullTrace, "graphql/tracing/null_trace"
11
+
12
+ autoload :ActiveSupportNotificationsTracing, "graphql/tracing/active_support_notifications_tracing"
13
+ autoload :PlatformTracing, "graphql/tracing/platform_tracing"
14
+ autoload :AppOpticsTracing, "graphql/tracing/appoptics_tracing"
15
+ autoload :AppsignalTracing, "graphql/tracing/appsignal_tracing"
16
+ autoload :DataDogTracing, "graphql/tracing/data_dog_tracing"
17
+ autoload :NewRelicTracing, "graphql/tracing/new_relic_tracing"
18
+ autoload :NotificationsTracing, "graphql/tracing/notifications_tracing"
19
+ autoload :ScoutTracing, "graphql/tracing/scout_tracing"
20
+ autoload :StatsdTracing, "graphql/tracing/statsd_tracing"
21
+ autoload :PrometheusTracing, "graphql/tracing/prometheus_tracing"
22
+
23
+ autoload :ActiveSupportNotificationsTrace, "graphql/tracing/active_support_notifications_trace"
24
+ autoload :PlatformTrace, "graphql/tracing/platform_trace"
25
+ autoload :AppOpticsTrace, "graphql/tracing/appoptics_trace"
26
+ autoload :AppsignalTrace, "graphql/tracing/appsignal_trace"
27
+ autoload :DataDogTrace, "graphql/tracing/data_dog_trace"
28
+ autoload :NewRelicTrace, "graphql/tracing/new_relic_trace"
29
+ autoload :NotificationsTrace, "graphql/tracing/notifications_trace"
30
+ autoload :SentryTrace, "graphql/tracing/sentry_trace"
31
+ autoload :ScoutTrace, "graphql/tracing/scout_trace"
32
+ autoload :StatsdTrace, "graphql/tracing/statsd_trace"
33
+ autoload :PrometheusTrace, "graphql/tracing/prometheus_trace"
36
34
 
37
35
  # Objects may include traceable to gain a `.trace(...)` method.
38
36
  # The object must have a `@tracers` ivar of type `Array<<#trace(k, d, &b)>>`.
@@ -18,6 +18,7 @@ module GraphQL
18
18
  self.node_type = nil
19
19
  self.edge_class = nil
20
20
  }
21
+ child_class.default_broadcastable(nil)
21
22
  add_page_info_field(child_class)
22
23
  end
23
24
 
@@ -31,12 +32,21 @@ module GraphQL
31
32
  child_class.edge_type = nil
32
33
  child_class.node_type = nil
33
34
  child_class.edge_class = nil
35
+ child_class.default_broadcastable(default_broadcastable?)
34
36
  end
35
37
 
36
38
  def default_relay?
37
39
  true
38
40
  end
39
41
 
42
+ def default_broadcastable?
43
+ @default_broadcastable
44
+ end
45
+
46
+ def default_broadcastable(new_value)
47
+ @default_broadcastable = new_value
48
+ end
49
+
40
50
  # @return [Class]
41
51
  attr_reader :node_type
42
52
 
@@ -186,7 +196,7 @@ module GraphQL
186
196
  def edges
187
197
  # Assume that whatever authorization needed to happen
188
198
  # already happened at the connection level.
189
- current_runtime_state = Thread.current[:__graphql_runtime_info]
199
+ current_runtime_state = Fiber[:__graphql_runtime_info]
190
200
  query_runtime_state = current_runtime_state[context.query]
191
201
  query_runtime_state.was_authorized_by_scope_items = @object.was_authorized_by_scope_items?
192
202
  @object.edges
@@ -195,7 +205,7 @@ module GraphQL
195
205
  def nodes
196
206
  # Assume that whatever authorization needed to happen
197
207
  # already happened at the connection level.
198
- current_runtime_state = Thread.current[:__graphql_runtime_info]
208
+ current_runtime_state = Fiber[:__graphql_runtime_info]
199
209
  query_runtime_state = current_runtime_state[context.query]
200
210
  query_runtime_state.was_authorized_by_scope_items = @object.was_authorized_by_scope_items?
201
211
  @object.nodes