Multiplex

Some clients may send several queries to the server at once (for example, Apollo Client’s query batching). You can execute them concurrently with Schema#multiplex.

Multiplex runs have their own context, analyzers and instrumentation.

Concurrent Execution

To run queries concurrently, build an array of query options, using query: for the query string. For example:

# Prepare the context for each query:
context = {
  current_user: current_user,
}

# Prepare the query options:
queries = [
  {
   query: "query Query1 { someField }",
   variables: {},
   operation_name: 'Query1',
   context: context,
 },
 {
   query: "query Query2 ($num: Int){ plusOne(num: $num) }",
   variables: { num: 3 },
   operation_name: 'Query2',
   context: context,
 }
]

Then, pass them to Schema#multiplex:

results = MySchema.multiplex(queries)

results will contain the result for each query in queries.

Validation and Error Handling

Each query is validated and analyzed independently. The results array may include a mix of successful results and failed results

Multiplex-Level Context

You can add values to Execution::Multiplex#context by providing a context: hash:

MySchema.multiplex(queries, context: { current_user: current_user })

This will be available to instrumentation as multiplex.context[:current_user] (see below).

Multiplex-Level Analysis

You can analyze all queries in a multiplex by adding a multiplex analyzer. For example:

MySchema = GraphQL::Schema.define do
  # ...
  multiplex_analyzer(MyAnalyzer)
end

The API is the same as query analyzers , with some considerations:

Multiplex analyzers may return AnalysisError to halt execution of the whole multiplex.

Multiplex Instrumentation

You can add hooks for each multiplex run with multiplex instrumentation.

An instrumenter must implement .before_multiplex(multiplex) and .after_multiplex(multiplex). Then, it can be mounted with instrument(:multiplex, MyMultiplexAnalyzer). See Execution::Multiplex for available methods.

For example:

# Count how many queries are in the multiplex run:
module MultiplexCounter
  def self.before_multiplex(multiplex)
    Rails.logger.info("Multiplex size: #{multiplex.queries.length}")
  end

  def self.after_multiplex(multiplex)
  end
end

# ...

MySchema = GraphQL::Schema.define do
  # ...
  instrument(:multiplex, MultiplexCounter)
end

Now, MultiplexCounter.before_multiplex will be called before each multiplex and .after_multiplex will run after each multiplex.