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 ¶
var MaxPooledArrayCollectorSize = 1000
MaxPooledArrayCollectorSize sets the threshold for reusing an array collector
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
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 ¶
A ResolveCompleteCallback is used by ExecutionListener. See above.
type Variables ¶
type Variables schema.LiteralObject
Variables represents variables passed to the query
func NewVariablesFromJSON ¶
NewVariablesFromJSON creates a Variables struct from JSON text