query

package
v0.0.0-...-02cfa7b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 16, 2023 License: Apache-2.0 Imports: 7 Imported by: 1

Documentation

Overview

Package query provides all the code to prepare and execute a GraphQL query.

To execute a query one needs three things: a root object, a query operation and a schema. These are used as follows:

  • root object - provides the root object the query operation will apply to.
  • query operation - specifies a GraphQL query to execute. The query contains a description of what data is selected.
  • schema - provides the model of the data the query is written against

Design notes:

  • No reflection allowed in this package. All things that would require reflection should happen via operations defined on types in the schema. For example, instead of using reflection to iterate over a slice, the list selector uses the schema.ListValue interface to perform the iteration. This allows resolvers to be implemented using reflection or not.

  • Threading model is one goroutine per query execution. A resolver may return an asynchronous value (see below) but the results are collected on the query processor thread. This means that none of the structures in this package need to be concerned with multi-threaded access: queries are built once, and never mutated, and a single execution of a query happens on a single thread.

  • Resolution model is a depth-first walk of the query tree, stopping at asynchronous nodes.

    An asynchronous node is one where the resolver returns a schema.AsyncValue object. In this case, the resolver is expected to have enqueued work to be done in a separate goroutine (or, equivalently, signaled an outside system to begin a job) prior to returning the AsyncValue. The AsyncValue represents a handle to the work that was enqueued. Invoking the Await method on the AsyncValue will initiate a blocking wait for the results of the computation.

    When an async node is encountered, the system enqueues a callback to await the results at a later time, and proceeds with the next non-child node in the walk. After the tree has been fully walked in this manner, NotifyIdle is called on the query listener associated with the execution, and each AsyncValue is awaited. As the results arrive, depth first walking in the same manner as above is initiated on each sub-tree rooted at a newly resolved async value.

    As an example, assume the following query lookupFooAsync { a { bAsync { c d } } e { f { gAsync { h i } } } } The order of operations to process this query would be: resolve lookupFooAsync notify idle await lookupFooAsync resolve a resolve bAsync resolve e resolve f resolve gAsync notify idle await bAsync await gAsync resolve c resolve d resolve h resolve i

    The goal of this approach is to allow efficient batching of queries to data stores. The NotifyIdle callback is a perfect place to batch schedule requests to data stores. Scheduling work in NotifyIdle is roughly equivalent to scheduling on next tick in an event loop based system.

Index

Constants

This section is empty.

Variables

View Source
var MaxPooledArrayCollectorSize = 1000

MaxPooledArrayCollectorSize sets the threshold for reusing an array collector

View Source
var MaxPooledObjectCollectorSize = 100

MaxPooledObjectCollectorSize sets the threshold for reusing an object collector

Functions

This section is empty.

Types

type BaseExecutionListener

type BaseExecutionListener struct{}

A BaseExecutionListener implements ExecutionListener to do nothing

func (BaseExecutionListener) NotifyError

func (BaseExecutionListener) NotifyError(err error)

NotifyError implements ExecutionListener

func (BaseExecutionListener) NotifyIdle

func (BaseExecutionListener) NotifyIdle()

NotifyIdle implements ExecutionListener

func (BaseExecutionListener) NotifyResolve

func (BaseExecutionListener) NotifyResolve(queryField *ast.Field, schemaField *schema.FieldDescriptor) (ResolveCompleteCallback, error)

NotifyResolve implements ExecutionListener

type Batch

type Batch struct {
	// contains filtered or unexported fields
}

Batch contains a batch of queries that execute together using the same context and listener

func (*Batch) Add

func (b *Batch) Add(q *PreparedQuery, rootValue interface{}, variables Variables)

Add adds a query to this batch

func (*Batch) Execute

func (b *Batch) Execute(ctx context.Context, listener ExecutionListener) [][]byte

Execute executes the entire batch of queries

type ExecutionListener

type ExecutionListener interface {
	// Notifies that execution is entering the selection of the specified field.
	//
	// If this method returns a ResolveCompleteCallback it will be called after
	// the value is resolved, with the result of resolving the value.
	//
	// If the error return value is non-nil, resolution of this field is skipped,
	// and the error is returned to the client.  The ResultListener is not invoked
	// in this case.
	NotifyResolve(queryField *ast.Field, schemaField *schema.FieldDescriptor) (ResolveCompleteCallback, error)

	// Notifies the listener that all synchronously resolvable query nodes have
	// been processed, and awaiting the results is about to begin.  This is a good
	// time for a listener to schedule batch loads.
	NotifyIdle()

	// Notifies the listener that an error occurred executing the query.
	NotifyError(err error)
}

An ExecutionListener can be used to trace the execution of a query. It is useful for logging, or scheduling work on idle

type PreparedQuery

type PreparedQuery struct {
	// contains filtered or unexported fields
}

A PreparedQuery is a compiled query that can be executed given a root value and query context

func PrepareQuery

func PrepareQuery(query string, operationName string, schema *schema.Schema) (*PreparedQuery, error)

PrepareQuery parses the supplied query text, and compiles it to a PreparedQuery which can then be executed many times. If the supplied query is invalid, nil and an error describing the problem are returned.

func (*PreparedQuery) Execute

func (q *PreparedQuery) Execute(ctx context.Context, rootValue interface{}, variables Variables, listener ExecutionListener) []byte

Execute runs this query, and returns the serialized results.

type ResolveCompleteCallback

type ResolveCompleteCallback func(interface{}, error) error

A ResolveCompleteCallback is used by ExecutionListener. See above.

type Variables

type Variables schema.LiteralObject

Variables represents variables passed to the query

func NewVariablesFromJSON

func NewVariablesFromJSON(j []byte) (Variables, error)

NewVariablesFromJSON creates a Variables struct from JSON text

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL