graphql 2.0.32 → 2.5.22
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/generators/graphql/detailed_trace_generator.rb +77 -0
- data/lib/generators/graphql/install/mutation_root_generator.rb +2 -2
- data/lib/generators/graphql/install/templates/base_mutation.erb +2 -0
- data/lib/generators/graphql/install/templates/mutation_type.erb +2 -0
- data/lib/generators/graphql/install_generator.rb +49 -0
- data/lib/generators/graphql/orm_mutations_base.rb +1 -1
- data/lib/generators/graphql/templates/base_argument.erb +2 -0
- data/lib/generators/graphql/templates/base_connection.erb +2 -0
- data/lib/generators/graphql/templates/base_edge.erb +2 -0
- data/lib/generators/graphql/templates/base_enum.erb +2 -0
- data/lib/generators/graphql/templates/base_field.erb +2 -0
- data/lib/generators/graphql/templates/base_input_object.erb +2 -0
- data/lib/generators/graphql/templates/base_interface.erb +2 -0
- data/lib/generators/graphql/templates/base_object.erb +2 -0
- data/lib/generators/graphql/templates/base_resolver.erb +8 -0
- data/lib/generators/graphql/templates/base_scalar.erb +2 -0
- data/lib/generators/graphql/templates/base_union.erb +2 -0
- data/lib/generators/graphql/templates/create_graphql_detailed_traces.erb +10 -0
- data/lib/generators/graphql/templates/graphql_controller.erb +2 -0
- data/lib/generators/graphql/templates/loader.erb +2 -0
- data/lib/generators/graphql/templates/mutation.erb +2 -0
- data/lib/generators/graphql/templates/node_type.erb +2 -0
- data/lib/generators/graphql/templates/query_type.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +5 -0
- data/lib/generators/graphql/type_generator.rb +1 -1
- data/lib/graphql/analysis/analyzer.rb +90 -0
- data/lib/graphql/analysis/field_usage.rb +82 -0
- data/lib/graphql/analysis/max_query_complexity.rb +20 -0
- data/lib/graphql/analysis/max_query_depth.rb +20 -0
- data/lib/graphql/analysis/query_complexity.rb +263 -0
- data/lib/graphql/analysis/query_depth.rb +58 -0
- data/lib/graphql/analysis/visitor.rb +280 -0
- data/lib/graphql/analysis.rb +95 -1
- data/lib/graphql/autoload.rb +38 -0
- data/lib/graphql/backtrace/table.rb +118 -55
- data/lib/graphql/backtrace.rb +1 -19
- data/lib/graphql/coercion_error.rb +1 -9
- data/lib/graphql/current.rb +57 -0
- data/lib/graphql/dashboard/application_controller.rb +41 -0
- data/lib/graphql/dashboard/detailed_traces.rb +47 -0
- data/lib/graphql/dashboard/installable.rb +22 -0
- data/lib/graphql/dashboard/landings_controller.rb +9 -0
- data/lib/graphql/dashboard/limiters.rb +93 -0
- data/lib/graphql/dashboard/operation_store.rb +199 -0
- data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.css +6 -0
- data/lib/graphql/dashboard/statics/bootstrap-5.3.3.min.js +7 -0
- data/lib/graphql/dashboard/statics/charts.min.css +1 -0
- data/lib/graphql/dashboard/statics/dashboard.css +30 -0
- data/lib/graphql/dashboard/statics/dashboard.js +143 -0
- data/lib/graphql/dashboard/statics/header-icon.png +0 -0
- data/lib/graphql/dashboard/statics/icon.png +0 -0
- data/lib/graphql/dashboard/statics_controller.rb +31 -0
- data/lib/graphql/dashboard/subscriptions.rb +97 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/detailed_traces/traces/index.html.erb +45 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/landings/show.html.erb +18 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/limiters/limiters/show.html.erb +62 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/not_installed.html.erb +18 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/_form.html.erb +24 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/edit.html.erb +21 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/index.html.erb +69 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/clients/new.html.erb +7 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/index.html.erb +39 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/index_entries/show.html.erb +32 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/index.html.erb +81 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/operation_store/operations/show.html.erb +71 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/subscriptions/show.html.erb +41 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/index.html.erb +55 -0
- data/lib/graphql/dashboard/views/graphql/dashboard/subscriptions/topics/show.html.erb +40 -0
- data/lib/graphql/dashboard/views/layouts/graphql/dashboard/application.html.erb +108 -0
- data/lib/graphql/dashboard.rb +96 -0
- data/lib/graphql/dataloader/active_record_association_source.rb +84 -0
- data/lib/graphql/dataloader/active_record_source.rb +47 -0
- data/lib/graphql/dataloader/async_dataloader.rb +112 -0
- data/lib/graphql/dataloader/null_dataloader.rb +55 -10
- data/lib/graphql/dataloader/request.rb +5 -0
- data/lib/graphql/dataloader/source.rb +35 -12
- data/lib/graphql/dataloader.rb +224 -149
- data/lib/graphql/date_encoding_error.rb +1 -1
- data/lib/graphql/dig.rb +2 -1
- data/lib/graphql/duration_encoding_error.rb +16 -0
- data/lib/graphql/execution/interpreter/argument_value.rb +5 -1
- data/lib/graphql/execution/interpreter/arguments_cache.rb +5 -10
- data/lib/graphql/execution/interpreter/resolve.rb +23 -25
- data/lib/graphql/execution/interpreter/runtime/graphql_result.rb +228 -0
- data/lib/graphql/execution/interpreter/runtime.rb +363 -434
- data/lib/graphql/execution/interpreter.rb +91 -164
- data/lib/graphql/execution/lookahead.rb +105 -31
- data/lib/graphql/execution/multiplex.rb +7 -6
- data/lib/graphql/execution/next/field_resolve_step.rb +711 -0
- data/lib/graphql/execution/next/load_argument_step.rb +60 -0
- data/lib/graphql/execution/next/prepare_object_step.rb +129 -0
- data/lib/graphql/execution/next/runner.rb +389 -0
- data/lib/graphql/execution/next/selections_step.rb +37 -0
- data/lib/graphql/execution/next.rb +70 -0
- data/lib/graphql/execution.rb +1 -0
- data/lib/graphql/execution_error.rb +13 -10
- data/lib/graphql/introspection/directive_location_enum.rb +1 -1
- data/lib/graphql/introspection/directive_type.rb +7 -3
- data/lib/graphql/introspection/dynamic_fields.rb +5 -1
- data/lib/graphql/introspection/entry_points.rb +20 -6
- data/lib/graphql/introspection/enum_value_type.rb +5 -5
- data/lib/graphql/introspection/field_type.rb +13 -5
- data/lib/graphql/introspection/input_value_type.rb +21 -13
- data/lib/graphql/introspection/schema_type.rb +8 -11
- data/lib/graphql/introspection/type_type.rb +64 -28
- data/lib/graphql/invalid_name_error.rb +1 -1
- data/lib/graphql/invalid_null_error.rb +26 -17
- data/lib/graphql/language/block_string.rb +34 -18
- data/lib/graphql/language/cache.rb +13 -0
- data/lib/graphql/language/comment.rb +18 -0
- data/lib/graphql/language/definition_slice.rb +1 -1
- data/lib/graphql/language/document_from_schema_definition.rb +90 -61
- data/lib/graphql/language/lexer.rb +319 -193
- data/lib/graphql/language/nodes.rb +136 -77
- data/lib/graphql/language/parser.rb +807 -1985
- data/lib/graphql/language/printer.rb +324 -151
- data/lib/graphql/language/sanitized_printer.rb +21 -23
- data/lib/graphql/language/static_visitor.rb +171 -0
- data/lib/graphql/language/visitor.rb +23 -83
- data/lib/graphql/language.rb +71 -1
- data/lib/graphql/load_application_object_failed_error.rb +5 -1
- data/lib/graphql/pagination/array_connection.rb +6 -6
- data/lib/graphql/pagination/connection.rb +30 -1
- data/lib/graphql/pagination/connections.rb +32 -0
- data/lib/graphql/pagination/mongoid_relation_connection.rb +1 -2
- data/lib/graphql/query/context/scoped_context.rb +101 -0
- data/lib/graphql/query/context.rb +82 -144
- data/lib/graphql/query/null_context.rb +15 -18
- data/lib/graphql/query/partial.rb +179 -0
- data/lib/graphql/query/validation_pipeline.rb +4 -4
- data/lib/graphql/query/variable_validation_error.rb +1 -1
- data/lib/graphql/query/variables.rb +3 -3
- data/lib/graphql/query.rb +126 -81
- data/lib/graphql/railtie.rb +16 -6
- data/lib/graphql/rake_task.rb +3 -12
- data/lib/graphql/rubocop/graphql/base_cop.rb +1 -1
- data/lib/graphql/rubocop/graphql/field_type_in_block.rb +144 -0
- data/lib/graphql/rubocop/graphql/root_types_in_block.rb +38 -0
- data/lib/graphql/rubocop.rb +2 -0
- data/lib/graphql/schema/addition.rb +26 -13
- data/lib/graphql/schema/always_visible.rb +7 -2
- data/lib/graphql/schema/argument.rb +75 -9
- data/lib/graphql/schema/base_64_encoder.rb +3 -5
- data/lib/graphql/schema/build_from_definition.rb +123 -60
- data/lib/graphql/schema/directive/flagged.rb +4 -2
- data/lib/graphql/schema/directive/one_of.rb +12 -0
- data/lib/graphql/schema/directive/specified_by.rb +14 -0
- data/lib/graphql/schema/directive.rb +54 -2
- data/lib/graphql/schema/enum.rb +110 -27
- data/lib/graphql/schema/enum_value.rb +10 -2
- data/lib/graphql/schema/field/connection_extension.rb +15 -49
- data/lib/graphql/schema/field/scope_extension.rb +23 -7
- data/lib/graphql/schema/field.rb +245 -118
- data/lib/graphql/schema/field_extension.rb +34 -1
- data/lib/graphql/schema/has_single_input_argument.rb +160 -0
- data/lib/graphql/schema/input_object.rb +116 -60
- data/lib/graphql/schema/interface.rb +34 -16
- data/lib/graphql/schema/introspection_system.rb +8 -17
- data/lib/graphql/schema/late_bound_type.rb +4 -0
- data/lib/graphql/schema/list.rb +3 -3
- data/lib/graphql/schema/loader.rb +3 -4
- data/lib/graphql/schema/member/base_dsl_methods.rb +18 -2
- data/lib/graphql/schema/member/has_arguments.rb +132 -100
- data/lib/graphql/schema/member/has_authorization.rb +35 -0
- data/lib/graphql/schema/member/has_dataloader.rb +99 -0
- data/lib/graphql/schema/member/has_deprecation_reason.rb +15 -0
- data/lib/graphql/schema/member/has_directives.rb +4 -4
- data/lib/graphql/schema/member/has_fields.rb +115 -15
- data/lib/graphql/schema/member/has_interfaces.rb +26 -12
- data/lib/graphql/schema/member/has_unresolved_type_error.rb +5 -1
- data/lib/graphql/schema/member/has_validators.rb +1 -1
- data/lib/graphql/schema/member/relay_shortcuts.rb +1 -1
- data/lib/graphql/schema/member/scoped.rb +19 -0
- data/lib/graphql/schema/member/type_system_helpers.rb +17 -4
- data/lib/graphql/schema/member/validates_input.rb +3 -3
- data/lib/graphql/schema/member.rb +6 -0
- data/lib/graphql/schema/mutation.rb +7 -0
- data/lib/graphql/schema/object.rb +34 -8
- data/lib/graphql/schema/printer.rb +9 -7
- data/lib/graphql/schema/ractor_shareable.rb +79 -0
- data/lib/graphql/schema/relay_classic_mutation.rb +6 -129
- data/lib/graphql/schema/resolver.rb +90 -32
- data/lib/graphql/schema/scalar.rb +4 -9
- data/lib/graphql/schema/subscription.rb +63 -10
- data/lib/graphql/schema/timeout.rb +19 -2
- data/lib/graphql/schema/type_expression.rb +2 -2
- data/lib/graphql/schema/union.rb +2 -2
- data/lib/graphql/schema/unique_within_type.rb +1 -1
- data/lib/graphql/schema/validator/all_validator.rb +62 -0
- data/lib/graphql/schema/validator/required_validator.rb +92 -11
- data/lib/graphql/schema/validator.rb +3 -1
- data/lib/graphql/schema/visibility/migration.rb +188 -0
- data/lib/graphql/schema/visibility/profile.rb +445 -0
- data/lib/graphql/schema/visibility/visit.rb +190 -0
- data/lib/graphql/schema/visibility.rb +311 -0
- data/lib/graphql/schema/warden.rb +275 -103
- data/lib/graphql/schema.rb +950 -210
- data/lib/graphql/static_validation/all_rules.rb +3 -3
- data/lib/graphql/static_validation/base_visitor.rb +7 -6
- data/lib/graphql/static_validation/literal_validator.rb +6 -7
- data/lib/graphql/static_validation/rules/argument_literals_are_compatible.rb +1 -1
- data/lib/graphql/static_validation/rules/argument_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/arguments_are_defined.rb +3 -2
- data/lib/graphql/static_validation/rules/directives_are_defined.rb +3 -3
- data/lib/graphql/static_validation/rules/directives_are_in_valid_locations.rb +2 -0
- data/lib/graphql/static_validation/rules/fields_are_defined_on_type.rb +12 -2
- data/lib/graphql/static_validation/rules/fields_have_appropriate_selections.rb +47 -13
- data/lib/graphql/static_validation/rules/fields_will_merge.rb +88 -25
- data/lib/graphql/static_validation/rules/fields_will_merge_error.rb +10 -2
- data/lib/graphql/static_validation/rules/fragment_spreads_are_possible.rb +3 -3
- data/lib/graphql/static_validation/rules/fragment_types_exist.rb +12 -2
- data/lib/graphql/static_validation/rules/fragments_are_on_composite_types.rb +1 -1
- data/lib/graphql/static_validation/rules/mutation_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/no_definitions_are_present.rb +1 -1
- data/lib/graphql/static_validation/rules/not_single_subscription_error.rb +25 -0
- data/lib/graphql/static_validation/rules/query_root_exists.rb +1 -1
- data/lib/graphql/static_validation/rules/required_arguments_are_present.rb +5 -5
- data/lib/graphql/static_validation/rules/required_input_object_attributes_are_present.rb +5 -5
- data/lib/graphql/static_validation/rules/subscription_root_exists_and_single_subscription_selection.rb +26 -0
- data/lib/graphql/static_validation/rules/unique_directives_per_location.rb +7 -3
- data/lib/graphql/static_validation/rules/variable_default_values_are_correctly_typed.rb +18 -27
- data/lib/graphql/static_validation/rules/variable_names_are_unique.rb +1 -1
- data/lib/graphql/static_validation/rules/variable_usages_are_allowed.rb +2 -2
- data/lib/graphql/static_validation/rules/variables_are_input_types.rb +11 -2
- data/lib/graphql/static_validation/validation_context.rb +21 -5
- data/lib/graphql/static_validation/validator.rb +9 -1
- data/lib/graphql/static_validation.rb +0 -1
- data/lib/graphql/subscriptions/action_cable_subscriptions.rb +8 -5
- data/lib/graphql/subscriptions/broadcast_analyzer.rb +11 -5
- data/lib/graphql/subscriptions/default_subscription_resolve_extension.rb +12 -10
- data/lib/graphql/subscriptions/event.rb +21 -4
- data/lib/graphql/subscriptions/serialize.rb +3 -1
- data/lib/graphql/subscriptions.rb +21 -17
- data/lib/graphql/testing/helpers.rb +161 -0
- data/lib/graphql/testing/mock_action_cable.rb +111 -0
- data/lib/graphql/testing.rb +3 -0
- data/lib/graphql/tracing/active_support_notifications_trace.rb +14 -3
- data/lib/graphql/tracing/active_support_notifications_tracing.rb +1 -1
- data/lib/graphql/tracing/appoptics_trace.rb +7 -3
- data/lib/graphql/tracing/appoptics_tracing.rb +9 -2
- data/lib/graphql/tracing/appsignal_trace.rb +32 -59
- data/lib/graphql/tracing/appsignal_tracing.rb +2 -0
- data/lib/graphql/tracing/call_legacy_tracers.rb +66 -0
- data/lib/graphql/tracing/data_dog_trace.rb +46 -162
- data/lib/graphql/tracing/data_dog_tracing.rb +2 -0
- data/lib/graphql/tracing/detailed_trace/active_record_backend.rb +74 -0
- data/lib/graphql/tracing/detailed_trace/memory_backend.rb +60 -0
- data/lib/graphql/tracing/detailed_trace/redis_backend.rb +72 -0
- data/lib/graphql/tracing/detailed_trace.rb +156 -0
- data/lib/graphql/tracing/legacy_hooks_trace.rb +75 -0
- data/lib/graphql/tracing/legacy_trace.rb +4 -61
- data/lib/graphql/tracing/monitor_trace.rb +283 -0
- data/lib/graphql/tracing/new_relic_trace.rb +47 -54
- data/lib/graphql/tracing/new_relic_tracing.rb +2 -0
- data/lib/graphql/tracing/notifications_trace.rb +183 -37
- data/lib/graphql/tracing/notifications_tracing.rb +2 -0
- data/lib/graphql/tracing/null_trace.rb +9 -0
- data/lib/graphql/tracing/perfetto_trace/trace.proto +141 -0
- data/lib/graphql/tracing/perfetto_trace/trace_pb.rb +33 -0
- data/lib/graphql/tracing/perfetto_trace.rb +864 -0
- data/lib/graphql/tracing/platform_tracing.rb +3 -1
- data/lib/graphql/tracing/{prometheus_tracing → prometheus_trace}/graphql_collector.rb +5 -1
- data/lib/graphql/tracing/prometheus_trace.rb +73 -73
- data/lib/graphql/tracing/prometheus_tracing.rb +2 -0
- data/lib/graphql/tracing/scout_trace.rb +32 -58
- data/lib/graphql/tracing/scout_tracing.rb +2 -0
- data/lib/graphql/tracing/sentry_trace.rb +82 -0
- data/lib/graphql/tracing/statsd_trace.rb +33 -45
- data/lib/graphql/tracing/statsd_tracing.rb +2 -0
- data/lib/graphql/tracing/trace.rb +112 -1
- data/lib/graphql/tracing.rb +31 -28
- data/lib/graphql/type_kinds.rb +2 -1
- data/lib/graphql/types/iso_8601_duration.rb +77 -0
- data/lib/graphql/types/relay/connection_behaviors.rb +44 -2
- data/lib/graphql/types/relay/edge_behaviors.rb +18 -0
- data/lib/graphql/types/relay/has_node_field.rb +13 -8
- data/lib/graphql/types/relay/has_nodes_field.rb +13 -8
- data/lib/graphql/types/relay/node_behaviors.rb +13 -2
- data/lib/graphql/types/relay/page_info_behaviors.rb +4 -0
- data/lib/graphql/types.rb +18 -10
- data/lib/graphql/unauthorized_enum_value_error.rb +13 -0
- data/lib/graphql/unauthorized_error.rb +5 -1
- data/lib/graphql/version.rb +1 -1
- data/lib/graphql.rb +71 -54
- data/readme.md +12 -2
- metadata +233 -37
- data/lib/graphql/analysis/ast/analyzer.rb +0 -84
- data/lib/graphql/analysis/ast/field_usage.rb +0 -57
- data/lib/graphql/analysis/ast/max_query_complexity.rb +0 -22
- data/lib/graphql/analysis/ast/max_query_depth.rb +0 -22
- data/lib/graphql/analysis/ast/query_complexity.rb +0 -230
- data/lib/graphql/analysis/ast/query_depth.rb +0 -55
- data/lib/graphql/analysis/ast/visitor.rb +0 -276
- data/lib/graphql/analysis/ast.rb +0 -81
- data/lib/graphql/backtrace/inspect_result.rb +0 -50
- data/lib/graphql/backtrace/trace.rb +0 -96
- data/lib/graphql/backtrace/tracer.rb +0 -80
- data/lib/graphql/deprecation.rb +0 -9
- data/lib/graphql/filter.rb +0 -59
- data/lib/graphql/language/parser.y +0 -560
- data/lib/graphql/language/token.rb +0 -34
- data/lib/graphql/schema/base_64_bp.rb +0 -26
- data/lib/graphql/schema/invalid_type_error.rb +0 -7
- data/lib/graphql/schema/null_mask.rb +0 -11
- data/lib/graphql/static_validation/rules/subscription_root_exists.rb +0 -17
- data/lib/graphql/static_validation/type_stack.rb +0 -216
- data/lib/graphql/subscriptions/instrumentation.rb +0 -28
|
@@ -20,196 +20,123 @@ module GraphQL
|
|
|
20
20
|
# @param queries [Array<GraphQL::Query, Hash>]
|
|
21
21
|
# @param context [Hash]
|
|
22
22
|
# @param max_complexity [Integer, nil]
|
|
23
|
-
# @return [Array<
|
|
23
|
+
# @return [Array<GraphQL::Query::Result>] One result per query
|
|
24
24
|
def run_all(schema, query_options, context: {}, max_complexity: schema.max_complexity)
|
|
25
25
|
queries = query_options.map do |opts|
|
|
26
|
-
case opts
|
|
26
|
+
query = case opts
|
|
27
27
|
when Hash
|
|
28
|
-
|
|
29
|
-
when GraphQL::Query
|
|
28
|
+
schema.query_class.new(schema, nil, **opts)
|
|
29
|
+
when GraphQL::Query, GraphQL::Query::Partial
|
|
30
30
|
opts
|
|
31
31
|
else
|
|
32
32
|
raise "Expected Hash or GraphQL::Query, not #{opts.class} (#{opts.inspect})"
|
|
33
33
|
end
|
|
34
|
+
query
|
|
34
35
|
end
|
|
35
36
|
|
|
37
|
+
return GraphQL::EmptyObjects::EMPTY_ARRAY if queries.empty?
|
|
38
|
+
|
|
36
39
|
multiplex = Execution::Multiplex.new(schema: schema, queries: queries, context: context, max_complexity: max_complexity)
|
|
37
|
-
multiplex.current_trace
|
|
40
|
+
trace = multiplex.current_trace
|
|
41
|
+
Fiber[:__graphql_current_multiplex] = multiplex
|
|
42
|
+
trace.execute_multiplex(multiplex: multiplex) do
|
|
38
43
|
schema = multiplex.schema
|
|
39
44
|
queries = multiplex.queries
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
# First, run multiplex instrumentation, then query instrumentation for each query
|
|
45
|
-
call_hooks(multiplex_instrumenters, multiplex, :before_multiplex, :after_multiplex) do
|
|
46
|
-
each_query_call_hooks(query_instrumenters, queries) do
|
|
47
|
-
schema = multiplex.schema
|
|
48
|
-
multiplex_analyzers = schema.multiplex_analyzers
|
|
49
|
-
queries = multiplex.queries
|
|
50
|
-
if multiplex.max_complexity
|
|
51
|
-
multiplex_analyzers += [GraphQL::Analysis::AST::MaxQueryComplexity]
|
|
52
|
-
end
|
|
45
|
+
multiplex_analyzers = schema.multiplex_analyzers
|
|
46
|
+
if multiplex.max_complexity
|
|
47
|
+
multiplex_analyzers += [GraphQL::Analysis::MaxQueryComplexity]
|
|
48
|
+
end
|
|
53
49
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
50
|
+
trace.begin_analyze_multiplex(multiplex, multiplex_analyzers)
|
|
51
|
+
schema.analysis_engine.analyze_multiplex(multiplex, multiplex_analyzers)
|
|
52
|
+
trace.end_analyze_multiplex(multiplex, multiplex_analyzers)
|
|
53
|
+
|
|
54
|
+
begin
|
|
55
|
+
# Since this is basically the batching context,
|
|
56
|
+
# share it for a whole multiplex
|
|
57
|
+
multiplex.context[:interpreter_instance] ||= multiplex.schema.query_execution_strategy(deprecation_warning: false).new
|
|
58
|
+
# Do as much eager evaluation of the query as possible
|
|
59
|
+
results = []
|
|
60
|
+
queries.each_with_index do |query, idx|
|
|
61
|
+
if query.subscription? && !query.subscription_update?
|
|
62
|
+
subs_namespace = query.context.namespace(:subscriptions)
|
|
63
|
+
subs_namespace[:events] = []
|
|
64
|
+
subs_namespace[:subscriptions] = {}
|
|
65
|
+
end
|
|
66
|
+
multiplex.dataloader.append_job {
|
|
67
|
+
operation = query.selected_operation
|
|
68
|
+
result = if operation.nil? || !query.valid? || !query.context.errors.empty?
|
|
69
|
+
NO_OPERATION
|
|
70
|
+
else
|
|
71
|
+
begin
|
|
72
|
+
# Although queries in a multiplex _share_ an Interpreter instance,
|
|
73
|
+
# they also have another item of state, which is private to that query
|
|
74
|
+
# in particular, assign it here:
|
|
75
|
+
runtime = Runtime.new(query: query)
|
|
76
|
+
query.context.namespace(:interpreter_runtime)[:runtime] = runtime
|
|
77
|
+
|
|
78
|
+
query.current_trace.execute_query(query: query) do
|
|
79
|
+
runtime.run_eager
|
|
81
80
|
end
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
rescue GraphQL::ExecutionError => err
|
|
82
|
+
query.context.errors << err
|
|
83
|
+
end
|
|
84
84
|
end
|
|
85
|
+
results[idx] = result
|
|
86
|
+
}
|
|
87
|
+
end
|
|
85
88
|
|
|
86
|
-
|
|
89
|
+
multiplex.dataloader.run(trace_query_lazy: multiplex)
|
|
87
90
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
runtime.delete_all_interpreter_context
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
}
|
|
108
|
-
multiplex.dataloader.run
|
|
109
|
-
|
|
110
|
-
# Then, find all errors and assign the result to the query object
|
|
111
|
-
results.each_with_index do |data_result, idx|
|
|
112
|
-
query = queries[idx]
|
|
113
|
-
# Assign the result so that it can be accessed in instrumentation
|
|
114
|
-
query.result_values = if data_result.equal?(NO_OPERATION)
|
|
115
|
-
if !query.valid? || query.context.errors.any?
|
|
116
|
-
# A bit weird, but `Query#static_errors` _includes_ `query.context.errors`
|
|
117
|
-
{ "errors" => query.static_errors.map(&:to_h) }
|
|
118
|
-
else
|
|
119
|
-
data_result
|
|
120
|
-
end
|
|
121
|
-
else
|
|
122
|
-
result = {
|
|
123
|
-
"data" => query.context.namespace(:interpreter_runtime)[:runtime].final_result
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if query.context.errors.any?
|
|
127
|
-
error_result = query.context.errors.map(&:to_h)
|
|
128
|
-
result["errors"] = error_result
|
|
129
|
-
end
|
|
91
|
+
# Then, find all errors and assign the result to the query object
|
|
92
|
+
results.each_with_index do |data_result, idx|
|
|
93
|
+
query = queries[idx]
|
|
94
|
+
if (events = query.context.namespace(:subscriptions)[:events]) && !events.empty?
|
|
95
|
+
schema.subscriptions.write_subscription(query, events)
|
|
96
|
+
end
|
|
97
|
+
# Assign the result so that it can be accessed in instrumentation
|
|
98
|
+
query.result_values = if data_result.equal?(NO_OPERATION)
|
|
99
|
+
if !query.valid? || !query.context.errors.empty?
|
|
100
|
+
# A bit weird, but `Query#static_errors` _includes_ `query.context.errors`
|
|
101
|
+
{ "errors" => query.static_errors.map(&:to_h) }
|
|
102
|
+
else
|
|
103
|
+
data_result
|
|
104
|
+
end
|
|
105
|
+
else
|
|
106
|
+
result = {}
|
|
130
107
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
query.result_values["extensions"] = query.context.namespace(:__query_result_extensions__)
|
|
135
|
-
end
|
|
136
|
-
# Get the Query::Result, not the Hash
|
|
137
|
-
results[idx] = query.result
|
|
108
|
+
if !query.context.errors.empty?
|
|
109
|
+
error_result = query.context.errors.map(&:to_h)
|
|
110
|
+
result["errors"] = error_result
|
|
138
111
|
end
|
|
139
112
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
ensure
|
|
147
|
-
queries.map { |query|
|
|
148
|
-
runtime = query.context.namespace(:interpreter_runtime)[:runtime]
|
|
149
|
-
if runtime
|
|
150
|
-
runtime.delete_all_interpreter_context
|
|
151
|
-
end
|
|
152
|
-
}
|
|
113
|
+
result["data"] = query.context.namespace(:interpreter_runtime)[:runtime].final_result
|
|
114
|
+
|
|
115
|
+
result
|
|
116
|
+
end
|
|
117
|
+
if query.context.namespace?(:__query_result_extensions__)
|
|
118
|
+
query.result_values["extensions"] = query.context.namespace(:__query_result_extensions__)
|
|
153
119
|
end
|
|
120
|
+
# Get the Query::Result, not the Hash
|
|
121
|
+
results[idx] = query.result
|
|
154
122
|
end
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
end
|
|
158
123
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
124
|
+
results
|
|
125
|
+
rescue Exception
|
|
126
|
+
# TODO rescue at a higher level so it will catch errors in analysis, too
|
|
127
|
+
# Assign values here so that the query's `@executed` becomes true
|
|
128
|
+
queries.map { |q| q.result_values ||= {} }
|
|
129
|
+
raise
|
|
130
|
+
ensure
|
|
131
|
+
Fiber[:__graphql_current_multiplex] = nil
|
|
132
|
+
queries.map { |query|
|
|
133
|
+
runtime = query.context.namespace(:interpreter_runtime)[:runtime]
|
|
134
|
+
if runtime
|
|
135
|
+
runtime.delete_all_interpreter_context
|
|
136
|
+
end
|
|
172
137
|
}
|
|
173
|
-
}
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
# Call each before hook, and if they all succeed, yield.
|
|
178
|
-
# If they don't all succeed, call after_ for each one that succeeded.
|
|
179
|
-
def call_hooks(instrumenters, object, before_hook_name, after_hook_name)
|
|
180
|
-
begin
|
|
181
|
-
successful = []
|
|
182
|
-
instrumenters.each do |instrumenter|
|
|
183
|
-
instrumenter.public_send(before_hook_name, object)
|
|
184
|
-
successful << instrumenter
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
# if any before hooks raise an exception, quit calling before hooks,
|
|
188
|
-
# but call the after hooks on anything that succeeded but also
|
|
189
|
-
# raise the exception that came from the before hook.
|
|
190
|
-
rescue GraphQL::ExecutionError => err
|
|
191
|
-
object.context.errors << err
|
|
192
|
-
rescue => e
|
|
193
|
-
raise call_after_hooks(successful, object, after_hook_name, e)
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
begin
|
|
197
|
-
yield # Call the user code
|
|
198
|
-
ensure
|
|
199
|
-
ex = call_after_hooks(successful, object, after_hook_name, nil)
|
|
200
|
-
raise ex if ex
|
|
201
|
-
end
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
def call_after_hooks(instrumenters, object, after_hook_name, ex)
|
|
205
|
-
instrumenters.reverse_each do |instrumenter|
|
|
206
|
-
begin
|
|
207
|
-
instrumenter.public_send(after_hook_name, object)
|
|
208
|
-
rescue => e
|
|
209
|
-
ex = e
|
|
210
138
|
end
|
|
211
139
|
end
|
|
212
|
-
ex
|
|
213
140
|
end
|
|
214
141
|
end
|
|
215
142
|
|
|
@@ -56,7 +56,14 @@ module GraphQL
|
|
|
56
56
|
else
|
|
57
57
|
@arguments = if @field
|
|
58
58
|
@query.after_lazy(@query.arguments_for(@ast_nodes.first, @field)) do |args|
|
|
59
|
-
|
|
59
|
+
case args
|
|
60
|
+
when Execution::Interpreter::Arguments
|
|
61
|
+
args.keyword_arguments
|
|
62
|
+
when GraphQL::ExecutionError
|
|
63
|
+
EmptyObjects::EMPTY_HASH
|
|
64
|
+
else
|
|
65
|
+
args
|
|
66
|
+
end
|
|
60
67
|
end
|
|
61
68
|
else
|
|
62
69
|
nil
|
|
@@ -80,6 +87,22 @@ module GraphQL
|
|
|
80
87
|
selection(field_name, selected_type: selected_type, arguments: arguments).selected?
|
|
81
88
|
end
|
|
82
89
|
|
|
90
|
+
# True if this node has a selection with alias matching `alias_name`.
|
|
91
|
+
# If `alias_name` is a String, it is treated as a GraphQL-style (camelized)
|
|
92
|
+
# field name and used verbatim. If `alias_name` is a Symbol, it is
|
|
93
|
+
# treated as a Ruby-style (underscored) name and camelized before comparing.
|
|
94
|
+
#
|
|
95
|
+
# If `arguments:` is provided, each provided key/value will be matched
|
|
96
|
+
# against the arguments in the next selection. This method will return false
|
|
97
|
+
# if any of the given `arguments:` are not present and matching in the next selection.
|
|
98
|
+
# (But, the next selection may contain _more_ than the given arguments.)
|
|
99
|
+
# @param alias_name [String, Symbol]
|
|
100
|
+
# @param arguments [Hash] Arguments which must match in the selection
|
|
101
|
+
# @return [Boolean]
|
|
102
|
+
def selects_alias?(alias_name, arguments: nil)
|
|
103
|
+
alias_selection(alias_name, arguments: arguments).selected?
|
|
104
|
+
end
|
|
105
|
+
|
|
83
106
|
# @return [Boolean] True if this lookahead represents a field that was requested
|
|
84
107
|
def selected?
|
|
85
108
|
true
|
|
@@ -92,45 +115,52 @@ module GraphQL
|
|
|
92
115
|
def selection(field_name, selected_type: @selected_type, arguments: nil)
|
|
93
116
|
next_field_defn = case field_name
|
|
94
117
|
when String
|
|
95
|
-
@query.
|
|
118
|
+
@query.types.field(selected_type, field_name)
|
|
96
119
|
when Symbol
|
|
97
120
|
# Try to avoid the `.to_s` below, if possible
|
|
98
121
|
all_fields = if selected_type.kind.fields?
|
|
99
|
-
@query.
|
|
122
|
+
@query.types.fields(selected_type)
|
|
100
123
|
else
|
|
101
124
|
# Handle unions by checking possible
|
|
102
|
-
@query.
|
|
125
|
+
@query.types
|
|
103
126
|
.possible_types(selected_type)
|
|
104
|
-
.map { |t| @query.
|
|
105
|
-
.flatten
|
|
127
|
+
.map { |t| @query.types.fields(t) }
|
|
128
|
+
.tap(&:flatten!)
|
|
106
129
|
end
|
|
107
130
|
|
|
131
|
+
|
|
108
132
|
if (match_by_orig_name = all_fields.find { |f| f.original_name == field_name })
|
|
109
133
|
match_by_orig_name
|
|
110
134
|
else
|
|
111
135
|
# Symbol#name is only present on 3.0+
|
|
112
136
|
sym_s = field_name.respond_to?(:name) ? field_name.name : field_name.to_s
|
|
113
137
|
guessed_name = Schema::Member::BuildType.camelize(sym_s)
|
|
114
|
-
@query.
|
|
138
|
+
@query.types.field(selected_type, guessed_name)
|
|
115
139
|
end
|
|
116
140
|
end
|
|
141
|
+
lookahead_for_selection(next_field_defn, selected_type, arguments)
|
|
142
|
+
end
|
|
117
143
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
end
|
|
144
|
+
# Like {#selection}, but for aliases.
|
|
145
|
+
# It returns a null object (check with {#selected?})
|
|
146
|
+
# @return [GraphQL::Execution::Lookahead]
|
|
147
|
+
def alias_selection(alias_name, selected_type: @selected_type, arguments: nil)
|
|
148
|
+
alias_cache_key = [alias_name, arguments]
|
|
149
|
+
return alias_selections[key] if alias_selections.key?(alias_name)
|
|
125
150
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
151
|
+
alias_node = lookup_alias_node(ast_nodes, alias_name)
|
|
152
|
+
return NULL_LOOKAHEAD unless alias_node
|
|
153
|
+
|
|
154
|
+
next_field_defn = @query.types.field(selected_type, alias_node.name)
|
|
155
|
+
|
|
156
|
+
alias_arguments = @query.arguments_for(alias_node, next_field_defn)
|
|
157
|
+
if alias_arguments.is_a?(::GraphQL::Execution::Interpreter::Arguments)
|
|
158
|
+
alias_arguments = alias_arguments.keyword_arguments
|
|
133
159
|
end
|
|
160
|
+
|
|
161
|
+
return NULL_LOOKAHEAD if arguments && arguments != alias_arguments
|
|
162
|
+
|
|
163
|
+
alias_selections[alias_cache_key] = lookahead_for_selection(next_field_defn, selected_type, alias_arguments, alias_name)
|
|
134
164
|
end
|
|
135
165
|
|
|
136
166
|
# Like {#selection}, but for all nodes.
|
|
@@ -160,7 +190,7 @@ module GraphQL
|
|
|
160
190
|
|
|
161
191
|
subselections_by_type.each do |type, ast_nodes_by_response_key|
|
|
162
192
|
ast_nodes_by_response_key.each do |response_key, ast_nodes|
|
|
163
|
-
field_defn = @query.
|
|
193
|
+
field_defn = @query.types.field(type, ast_nodes.first.name)
|
|
164
194
|
lookahead = Lookahead.new(query: @query, ast_nodes: ast_nodes, field: field_defn, owner_type: type)
|
|
165
195
|
subselections.push(lookahead)
|
|
166
196
|
end
|
|
@@ -243,7 +273,7 @@ module GraphQL
|
|
|
243
273
|
elsif arguments.nil? || arguments.empty?
|
|
244
274
|
selections_on_type[response_key] = [ast_selection]
|
|
245
275
|
else
|
|
246
|
-
field_defn = @query.
|
|
276
|
+
field_defn = @query.types.field(selected_type, ast_selection.name)
|
|
247
277
|
if arguments_match?(arguments, field_defn, ast_selection)
|
|
248
278
|
selections_on_type[response_key] = [ast_selection]
|
|
249
279
|
end
|
|
@@ -253,14 +283,14 @@ module GraphQL
|
|
|
253
283
|
subselections_on_type = selections_on_type
|
|
254
284
|
if (t = ast_selection.type)
|
|
255
285
|
# Assuming this is valid, that `t` will be found.
|
|
256
|
-
on_type = @query.
|
|
286
|
+
on_type = @query.types.type(t.name)
|
|
257
287
|
subselections_on_type = subselections_by_type[on_type] ||= {}
|
|
258
288
|
end
|
|
259
289
|
find_selections(subselections_by_type, subselections_on_type, on_type, ast_selection.selections, arguments)
|
|
260
290
|
when GraphQL::Language::Nodes::FragmentSpread
|
|
261
|
-
frag_defn =
|
|
291
|
+
frag_defn = lookup_fragment(ast_selection)
|
|
262
292
|
# Again, assuming a valid AST
|
|
263
|
-
on_type = @query.
|
|
293
|
+
on_type = @query.types.type(frag_defn.type.name)
|
|
264
294
|
subselections_on_type = subselections_by_type[on_type] ||= {}
|
|
265
295
|
find_selections(subselections_by_type, subselections_on_type, on_type, frag_defn.selections, arguments)
|
|
266
296
|
else
|
|
@@ -271,11 +301,11 @@ module GraphQL
|
|
|
271
301
|
|
|
272
302
|
# If a selection on `node` matches `field_name` (which is backed by `field_defn`)
|
|
273
303
|
# and matches the `arguments:` constraints, then add that node to `matches`
|
|
274
|
-
def find_selected_nodes(node, field_defn, arguments:, matches:)
|
|
304
|
+
def find_selected_nodes(node, field_name, field_defn, arguments:, matches:, alias_name: NOT_CONFIGURED)
|
|
275
305
|
return if skipped_by_directive?(node)
|
|
276
306
|
case node
|
|
277
307
|
when GraphQL::Language::Nodes::Field
|
|
278
|
-
if node.name ==
|
|
308
|
+
if node.name == field_name && (NOT_CONFIGURED.equal?(alias_name) || node.alias == alias_name)
|
|
279
309
|
if arguments.nil? || arguments.empty?
|
|
280
310
|
# No constraint applied
|
|
281
311
|
matches << node
|
|
@@ -284,10 +314,10 @@ module GraphQL
|
|
|
284
314
|
end
|
|
285
315
|
end
|
|
286
316
|
when GraphQL::Language::Nodes::InlineFragment
|
|
287
|
-
node.selections.each { |s| find_selected_nodes(s, field_defn, arguments: arguments, matches: matches) }
|
|
317
|
+
node.selections.each { |s| find_selected_nodes(s, field_name, field_defn, arguments: arguments, matches: matches, alias_name: alias_name) }
|
|
288
318
|
when GraphQL::Language::Nodes::FragmentSpread
|
|
289
|
-
frag_defn =
|
|
290
|
-
frag_defn.selections.each { |s| find_selected_nodes(s, field_defn, arguments: arguments, matches: matches) }
|
|
319
|
+
frag_defn = lookup_fragment(node)
|
|
320
|
+
frag_defn.selections.each { |s| find_selected_nodes(s, field_name, field_defn, arguments: arguments, matches: matches, alias_name: alias_name) }
|
|
291
321
|
else
|
|
292
322
|
raise "Unexpected selection comparison on #{node.class.name} (#{node})"
|
|
293
323
|
end
|
|
@@ -306,6 +336,50 @@ module GraphQL
|
|
|
306
336
|
query_kwargs.key?(arg_name_sym) && query_kwargs[arg_name_sym] == arg_value
|
|
307
337
|
end
|
|
308
338
|
end
|
|
339
|
+
|
|
340
|
+
def lookahead_for_selection(field_defn, selected_type, arguments, alias_name = NOT_CONFIGURED)
|
|
341
|
+
return NULL_LOOKAHEAD unless field_defn
|
|
342
|
+
|
|
343
|
+
next_nodes = []
|
|
344
|
+
field_name = field_defn.name
|
|
345
|
+
@ast_nodes.each do |ast_node|
|
|
346
|
+
ast_node.selections.each do |selection|
|
|
347
|
+
find_selected_nodes(selection, field_name, field_defn, arguments: arguments, matches: next_nodes, alias_name: alias_name)
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
return NULL_LOOKAHEAD if next_nodes.empty?
|
|
352
|
+
|
|
353
|
+
Lookahead.new(query: @query, ast_nodes: next_nodes, field: field_defn, owner_type: selected_type)
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
def alias_selections
|
|
357
|
+
return @alias_selections if defined?(@alias_selections)
|
|
358
|
+
@alias_selections ||= {}
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
def lookup_alias_node(nodes, name)
|
|
362
|
+
return if nodes.empty?
|
|
363
|
+
|
|
364
|
+
nodes.flat_map(&:children)
|
|
365
|
+
.flat_map { |child| unwrap_fragments(child) }
|
|
366
|
+
.find { |child| child.is_a?(GraphQL::Language::Nodes::Field) && child.alias == name }
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
def unwrap_fragments(node)
|
|
370
|
+
case node
|
|
371
|
+
when GraphQL::Language::Nodes::InlineFragment
|
|
372
|
+
node.children
|
|
373
|
+
when GraphQL::Language::Nodes::FragmentSpread
|
|
374
|
+
lookup_fragment(node).children
|
|
375
|
+
else
|
|
376
|
+
[node]
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
def lookup_fragment(ast_selection)
|
|
381
|
+
@query.fragments[ast_selection.name] || raise("Invariant: Can't look ahead to nonexistent fragment #{ast_selection.name} (found: #{@query.fragments.keys})")
|
|
382
|
+
end
|
|
309
383
|
end
|
|
310
384
|
end
|
|
311
385
|
end
|
|
@@ -32,14 +32,15 @@ module GraphQL
|
|
|
32
32
|
@queries = queries
|
|
33
33
|
@queries.each { |q| q.multiplex = self }
|
|
34
34
|
@context = context
|
|
35
|
-
@current_trace = @context[:trace] || schema.new_trace(multiplex: self)
|
|
36
35
|
@dataloader = @context[:dataloader] ||= @schema.dataloader_class.new
|
|
37
|
-
@tracers = schema.tracers + (context[:tracers] ||
|
|
38
|
-
# Support `context: {backtrace: true}`
|
|
39
|
-
if context[:backtrace] && !@tracers.include?(GraphQL::Backtrace::Tracer)
|
|
40
|
-
@tracers << GraphQL::Backtrace::Tracer
|
|
41
|
-
end
|
|
36
|
+
@tracers = schema.tracers + (context[:tracers] || EmptyObjects::EMPTY_ARRAY)
|
|
42
37
|
@max_complexity = max_complexity
|
|
38
|
+
@current_trace = context[:trace] ||= schema.new_trace(multiplex: self)
|
|
39
|
+
@logger = nil
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def logger
|
|
43
|
+
@logger ||= @schema.logger_for(context)
|
|
43
44
|
end
|
|
44
45
|
end
|
|
45
46
|
end
|