lib/graphql/execution/multiplex.rb in graphql-1.13.23 vs lib/graphql/execution/multiplex.rb in graphql-2.0.0
- old
+ new
@@ -43,34 +43,68 @@
end
@max_complexity = max_complexity
end
class << self
- def run_all(schema, query_options, **kwargs)
- queries = query_options.map { |opts| GraphQL::Query.new(schema, nil, **opts) }
- run_queries(schema, queries, **kwargs)
- end
-
# @param schema [GraphQL::Schema]
- # @param queries [Array<GraphQL::Query>]
+ # @param queries [Array<GraphQL::Query, Hash>]
# @param context [Hash]
# @param max_complexity [Integer, nil]
# @return [Array<Hash>] One result per query
- def run_queries(schema, queries, context: {}, max_complexity: schema.max_complexity)
+ def run_all(schema, query_options, context: {}, max_complexity: schema.max_complexity)
+ queries = query_options.map do |opts|
+ case opts
+ when Hash
+ GraphQL::Query.new(schema, nil, **opts)
+ when GraphQL::Query
+ opts
+ else
+ raise "Expected Hash or GraphQL::Query, not #{opts.class} (#{opts.inspect})"
+ end
+ end
+
multiplex = self.new(schema: schema, queries: queries, context: context, max_complexity: max_complexity)
multiplex.trace("execute_multiplex", { multiplex: multiplex }) do
- if supports_multiplexing?(schema)
- instrument_and_analyze(multiplex) do
- run_as_multiplex(multiplex)
+ GraphQL::Execution::Instrumentation.apply_instrumenters(multiplex) do
+ schema = multiplex.schema
+ multiplex_analyzers = schema.multiplex_analyzers
+ if multiplex.max_complexity
+ multiplex_analyzers += [GraphQL::Analysis::AST::MaxQueryComplexity]
end
- else
- if queries.length != 1
- raise ArgumentError, "Multiplexing doesn't support custom execution strategies, run one query at a time instead"
- else
- instrument_and_analyze(multiplex) do
- [run_one_legacy(schema, queries.first)]
+
+ schema.analysis_engine.analyze_multiplex(multiplex, multiplex_analyzers)
+
+ begin
+ multiplex.schema.query_execution_strategy.begin_multiplex(multiplex)
+ # Do as much eager evaluation of the query as possible
+ results = []
+ queries.each_with_index do |query, idx|
+ multiplex.dataloader.append_job { begin_query(results, idx, query, multiplex) }
end
+
+ multiplex.dataloader.run
+
+ # Then, work through lazy results in a breadth-first way
+ multiplex.dataloader.append_job {
+ multiplex.schema.query_execution_strategy.finish_multiplex(results, multiplex)
+ }
+ multiplex.dataloader.run
+
+ # Then, find all errors and assign the result to the query object
+ results.each_with_index do |data_result, idx|
+ query = queries[idx]
+ finish_query(data_result, query, multiplex)
+ # Get the Query::Result, not the Hash
+ results[idx] = query.result
+ end
+
+ results
+ rescue Exception
+ # TODO rescue at a higher level so it will catch errors in analysis, too
+ # Assign values here so that the query's `@executed` becomes true
+ queries.map { |q| q.result_values ||= {} }
+ raise
end
end
end
end
@@ -79,11 +113,10 @@
operation = query.selected_operation
result = if operation.nil? || !query.valid? || query.context.errors.any?
NO_OPERATION
else
begin
- # These were checked to be the same in `#supports_multiplexing?`
query.schema.query_execution_strategy.begin_query(query, multiplex)
rescue GraphQL::ExecutionError => err
query.context.errors << err
NO_OPERATION
end
@@ -92,44 +125,10 @@
nil
end
private
- def run_as_multiplex(multiplex)
-
- multiplex.schema.query_execution_strategy.begin_multiplex(multiplex)
- queries = multiplex.queries
- # Do as much eager evaluation of the query as possible
- results = []
- queries.each_with_index do |query, idx|
- multiplex.dataloader.append_job { begin_query(results, idx, query, multiplex) }
- end
-
- multiplex.dataloader.run
-
- # Then, work through lazy results in a breadth-first way
- multiplex.dataloader.append_job {
- multiplex.schema.query_execution_strategy.finish_multiplex(results, multiplex)
- }
- multiplex.dataloader.run
-
- # Then, find all errors and assign the result to the query object
- results.each_with_index do |data_result, idx|
- query = queries[idx]
- finish_query(data_result, query, multiplex)
- # Get the Query::Result, not the Hash
- results[idx] = query.result
- end
-
- results
- rescue Exception
- # TODO rescue at a higher level so it will catch errors in analysis, too
- # Assign values here so that the query's `@executed` becomes true
- queries.map { |q| q.result_values ||= {} }
- raise
- end
-
# @param data_result [Hash] The result for the "data" key, if any
# @param query [GraphQL::Query] The query which was run
# @return [Hash] final result of this query, including all values and errors
def finish_query(data_result, query, multiplex)
# Assign the result so that it can be accessed in instrumentation
@@ -151,65 +150,9 @@
result
end
if query.context.namespace?(:__query_result_extensions__)
query.result_values["extensions"] = query.context.namespace(:__query_result_extensions__)
- end
- end
-
- # use the old `query_execution_strategy` etc to run this query
- def run_one_legacy(schema, query)
- GraphQL::Deprecation.warn "Multiplex.run_one_legacy will be removed from GraphQL-Ruby 2.0, upgrade to the Interpreter to avoid this deprecated codepath: https://graphql-ruby.org/queries/interpreter.html"
-
- query.result_values = if !query.valid?
- all_errors = query.validation_errors + query.analysis_errors + query.context.errors
- if all_errors.any?
- { "errors" => all_errors.map(&:to_h) }
- else
- nil
- end
- else
- GraphQL::Query::Executor.new(query).result
- end
- end
-
- DEFAULT_STRATEGIES = [
- GraphQL::Execution::Execute,
- GraphQL::Execution::Interpreter
- ]
- # @return [Boolean] True if the schema is only using one strategy, and it's one that supports multiplexing.
- def supports_multiplexing?(schema)
- schema_strategies = [schema.query_execution_strategy, schema.mutation_execution_strategy, schema.subscription_execution_strategy]
- schema_strategies.uniq!
- schema_strategies.size == 1 && DEFAULT_STRATEGIES.include?(schema_strategies.first)
- end
-
- # Apply multiplex & query instrumentation to `queries`.
- #
- # It yields when the queries should be executed, then runs teardown.
- def instrument_and_analyze(multiplex)
- GraphQL::Execution::Instrumentation.apply_instrumenters(multiplex) do
- schema = multiplex.schema
- if schema.interpreter? && schema.analysis_engine != GraphQL::Analysis::AST
- raise <<-ERR
-Can't use `GraphQL::Execution::Interpreter` without `GraphQL::Analysis::AST`, please add this plugin to your schema:
-
- use GraphQL::Analysis::AST
-
-For information about the new analysis engine: https://graphql-ruby.org/queries/ast_analysis.html
-ERR
- end
- multiplex_analyzers = schema.multiplex_analyzers
- if multiplex.max_complexity
- multiplex_analyzers += if schema.using_ast_analysis?
- [GraphQL::Analysis::AST::MaxQueryComplexity]
- else
- [GraphQL::Analysis::MaxQueryComplexity.new(multiplex.max_complexity)]
- end
- end
-
- schema.analysis_engine.analyze_multiplex(multiplex, multiplex_analyzers)
- yield
end
end
end
end
end