Skip to content

Commit 1be44d0

Browse files
leebyronbenjie
andcommitted
Define 'execution' as in 'before execution begins'
Reintroduces #894 atop latest main Co-authored-by: Benjie <[email protected]>
1 parent 468d848 commit 1be44d0

5 files changed

Lines changed: 98 additions & 71 deletions

spec/Section 3 -- Type System.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ GraphQL supports two abstract types: interfaces and unions.
328328
An `Interface` defines a list of fields; `Object` types and other Interface
329329
types which implement this Interface are guaranteed to implement those fields.
330330
Whenever a field claims it will return an Interface type, it will return a valid
331-
implementing Object type during execution.
331+
implementing Object type during _execution_.
332332

333333
A `Union` defines a list of possible types; similar to interfaces, whenever the
334334
type system claims a union will be returned, one of the possible types will be
@@ -505,7 +505,7 @@ information on the serialization of scalars in common JSON and other formats.
505505
If a GraphQL service expects a scalar type as input to an argument, coercion is
506506
observable and the rules must be well defined. If an input value does not match
507507
a coercion rule, a _request error_ must be raised (input values are validated
508-
before execution begins).
508+
before _execution_ begins).
509509

510510
GraphQL has different constant literals to represent integer and floating-point
511511
input values, and coercion rules may apply differently depending on which type
@@ -810,7 +810,7 @@ And will yield the subset of each object type queried:
810810
**Field Ordering**
811811

812812
When querying an Object, the resulting mapping of fields are conceptually
813-
ordered in the same order in which they were encountered during execution,
813+
ordered in the same order in which they were encountered during _execution_,
814814
excluding fragments for which the type does not apply and fields or fragments
815815
that are skipped via `@skip` or `@include` directives. This ordering is
816816
correctly produced when using the {CollectFields()} algorithm.
@@ -2058,8 +2058,8 @@ directive @example on
20582058

20592059
Directives can also be used to annotate the type system definition language as
20602060
well, which can be a useful tool for supplying additional metadata in order to
2061-
generate GraphQL execution services, produce client generated runtime code, or
2062-
many other useful extensions of the GraphQL semantics.
2061+
generate GraphQL services, produce client generated runtime code, or many other
2062+
useful extensions of the GraphQL semantics.
20632063

20642064
In this example, the directive `@example` annotates field and argument
20652065
definitions:
@@ -2122,7 +2122,7 @@ directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
21222122
```
21232123

21242124
The `@skip` _built-in directive_ may be provided for fields, fragment spreads,
2125-
and inline fragments, and allows for conditional exclusion during execution as
2125+
and inline fragments, and allows for conditional exclusion during _execution_ as
21262126
described by the `if` argument.
21272127

21282128
In this example `experimentalField` will only be queried if the variable
@@ -2142,7 +2142,7 @@ directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
21422142

21432143
The `@include` _built-in directive_ may be provided for fields, fragment
21442144
spreads, and inline fragments, and allows for conditional inclusion during
2145-
execution as described by the `if` argument.
2145+
_execution_ as described by the `if` argument.
21462146

21472147
In this example `experimentalField` will only be queried if the variable
21482148
`$someTest` has the value `true`

spec/Section 4 -- Introspection.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ GraphQL supports type name introspection within any _selection set_ in an
7272
operation, with the single exception of selections at the root of a subscription
7373
operation. Type name introspection is accomplished via the meta-field
7474
`__typename: String!` on any Object, Interface, or Union. It returns the name of
75-
the concrete Object type at that point during execution.
75+
the concrete Object type at that point during _execution_.
7676

7777
This is most often used when querying against Interface or Union types to
7878
identify which actual Object type of the possible types has been returned.

spec/Section 5 -- Validation.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ given GraphQL schema.
77
An invalid request is still technically executable, and will always produce a
88
stable result as defined by the algorithms in the Execution section, however
99
that result may be ambiguous, surprising, or unexpected relative to a request
10-
containing validation errors, so execution should only occur for valid requests.
10+
containing validation errors, so _execution_ should only occur for valid
11+
requests.
1112

1213
Typically validation is performed in the context of a request immediately before
1314
execution, however a GraphQL service may execute a request without explicitly
@@ -108,7 +109,7 @@ input FindDogInput {
108109

109110
GraphQL execution will only consider the executable definitions Operation and
110111
Fragment. Type system definitions and extensions are not executable, and are not
111-
considered during execution.
112+
considered during _execution_.
112113

113114
To avoid ambiguity, a document containing {TypeSystemDefinitionOrExtension} is
114115
invalid for execution.
@@ -579,7 +580,7 @@ type that is either an Object, Interface or Union type.
579580
**Explanatory Text**
580581

581582
If multiple field selections with the same _response name_ are encountered
582-
during execution, the field and arguments to execute and the resulting value
583+
during _execution_, the field and arguments to execute and the resulting value
583584
should be unambiguous. Therefore any two field selections which might both be
584585
encountered for the same object are only valid if they are equivalent.
585586

spec/Section 6 -- Execution.md

Lines changed: 70 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ A GraphQL service generates a response from a request via execution.
1818
- {extensions} (optional): A map reserved for implementation-specific additional
1919
information.
2020

21-
Given this information, the result of {ExecuteRequest(schema, document,
22-
operationName, variableValues, initialValue)} produces the response, to be
23-
formatted according to the Response section below.
21+
Given this information, the result of {Request(schema, document, operationName,
22+
variableValues, initialValue)} produces the response, to be formatted according
23+
to the Response section below.
2424

2525
Implementations should not add additional properties to a _request_, which may
2626
conflict with future editions of the GraphQL specification. Instead,
@@ -39,27 +39,44 @@ and have no effect on the observable execution, validation, or response of a
3939
GraphQL document. Descriptions and comments on executable documents MAY be used
4040
for non-observable purposes, such as logging and other developer tools.
4141

42-
## Executing Requests
42+
## Processing Requests
4343

44-
To execute a request, the executor must have a parsed {Document} and a selected
44+
<a name="#sec-Executing-Requests">
45+
<!-- Legacy link, this section was previously titled "Executing Requests" -->
46+
</a>
47+
48+
To process a request, the executor must have a parsed {Document} and a selected
4549
operation name to run if the document defines multiple operations, otherwise the
4650
document is expected to only contain a single operation. The result of the
47-
request is determined by the result of executing this operation according to the
48-
"Executing Operations” section below.
51+
request is determined by the result of performing this operation according to
52+
the "Performing Operations” section below.
53+
54+
The {Request()} algorithm contains the preamble for _execution_, handling
55+
concerns such as determining the operation and coercing the inputs, before
56+
passing the request on to the relevant algorithm for the operation's type which
57+
then performs any other necessary preliminary steps (for example establishing
58+
the source event stream for subscription operations) and then initiates
59+
_execution_.
60+
61+
Note: An error raised before _execution_ begins will typically be a _request
62+
error_, and once _execution_ begins will typically be an _execution error_.
63+
64+
:: We define _execution_ as the process of executing the operation's _root
65+
selection set_ through {ExecuteRootSelectionSet()}, and hence _execution_ begins
66+
when {ExecuteRootSelectionSet()} is called for the first time in a request.
4967

50-
ExecuteRequest(schema, document, operationName, variableValues, initialValue):
68+
Request(schema, document, operationName, variableValues, initialValue):
5169

5270
- Let {operation} be the result of {GetOperation(document, operationName)}.
5371
- Let {coercedVariableValues} be the result of {CoerceVariableValues(schema,
5472
operation, variableValues)}.
5573
- If {operation} is a query operation:
56-
- Return {ExecuteQuery(operation, schema, coercedVariableValues,
57-
initialValue)}.
74+
- Return {Query(operation, schema, coercedVariableValues, initialValue)}.
5875
- Otherwise if {operation} is a mutation operation:
59-
- Return {ExecuteMutation(operation, schema, coercedVariableValues,
60-
initialValue)}.
76+
- Return {Mutation(operation, schema, coercedVariableValues, initialValue)}.
6177
- Otherwise if {operation} is a subscription operation:
62-
- Return {Subscribe(operation, schema, coercedVariableValues, initialValue)}.
78+
- Return {Subscription(operation, schema, coercedVariableValues,
79+
initialValue)}.
6380

6481
GetOperation(document, operationName):
6582

@@ -74,27 +91,28 @@ GetOperation(document, operationName):
7491

7592
### Validating Requests
7693

77-
As explained in the Validation section, only requests which pass all validation
78-
rules should be executed. If validation errors are known, they should be
79-
reported in the list of "errors" in the response and the request must fail
80-
without execution.
94+
As explained in the Validation section, only operations from documents which
95+
pass all validation rules should be executed. If validation errors are known,
96+
they should be reported in the list of "errors" in the response and the request
97+
must fail without execution.
8198

8299
Typically validation is performed in the context of a request immediately before
83-
execution, however a GraphQL service may execute a request without immediately
84-
validating it if that exact same request is known to have been validated before.
85-
A GraphQL service should only execute requests which _at some point_ were known
86-
to be free of any validation errors, and have since not changed.
100+
calling {Request()}, however a GraphQL service may process a request without
101+
immediately validating the document if that exact same document is known to have
102+
been validated before. A GraphQL service should only execute operations which
103+
_at some point_ were known to be free of any validation errors, and have since
104+
not changed.
87105

88-
For example: the request may be validated during development, provided it does
89-
not later change, or a service may validate a request once and memoize the
90-
result to avoid validating the same request again in the future.
106+
For example: the document may be validated during development, provided it does
107+
not later change, or a service may validate a document once and memoize the
108+
result to avoid validating the same document again in the future.
91109

92110
### Coercing Variable Values
93111

94112
If the operation has defined any variables, then the values for those variables
95113
need to be coerced using the input coercion rules of variable's declared type.
96114
If a _request error_ is encountered during input coercion of variable values,
97-
then the operation fails without execution.
115+
then the request fails without _execution_.
98116

99117
CoerceVariableValues(schema, operation, variableValues):
100118

@@ -131,7 +149,11 @@ CoerceVariableValues(schema, operation, variableValues):
131149

132150
Note: This algorithm is very similar to {CoerceArgumentValues()}.
133151

134-
## Executing Operations
152+
## Performing Operations
153+
154+
<a name="#sec-Executing-Operations">
155+
<!-- Legacy link, this section was previously titled "Executing Operations" -->
156+
</a>
135157

136158
The type system, as described in the "Type System" section of the spec, must
137159
provide a query root operation type. If mutations or subscriptions are
@@ -144,9 +166,9 @@ If the operation is a query, the result of the operation is the result of
144166
executing the operation’s _root selection set_ with the query root operation
145167
type.
146168

147-
An initial value may be provided when executing a query operation.
169+
An initial value may be provided when performing a query operation.
148170

149-
ExecuteQuery(query, schema, variableValues, initialValue):
171+
Query(query, schema, variableValues, initialValue):
150172

151173
- Let {queryType} be the root Query type in {schema}.
152174
- Assert: {queryType} is an Object type.
@@ -164,7 +186,7 @@ It is expected that the top level fields in a mutation operation perform
164186
side-effects on the underlying data system. Serial execution of the provided
165187
mutations ensures against race conditions during these side-effects.
166188

167-
ExecuteMutation(mutation, schema, variableValues, initialValue):
189+
Mutation(mutation, schema, variableValues, initialValue):
168190

169191
- Let {mutationType} be the root Mutation type in {schema}.
170192
- Assert: {mutationType} is an Object type.
@@ -176,12 +198,13 @@ ExecuteMutation(mutation, schema, variableValues, initialValue):
176198

177199
If the operation is a subscription, the result is an _event stream_ called the
178200
_response stream_ where each event in the event stream is the result of
179-
executing the operation for each new event on an underlying _source stream_.
201+
executing the operation’s _root selection set_ for each new event on an
202+
underlying _source stream_.
180203

181-
Executing a subscription operation creates a persistent function on the service
204+
Performing a subscription operation creates a persistent function on the service
182205
that maps an underlying _source stream_ to a returned _response stream_.
183206

184-
Subscribe(subscription, schema, variableValues, initialValue):
207+
Subscription(subscription, schema, variableValues, initialValue):
185208

186209
- Let {sourceStream} be the result of running
187210
{CreateSourceEventStream(subscription, schema, variableValues, initialValue)}.
@@ -190,9 +213,9 @@ Subscribe(subscription, schema, variableValues, initialValue):
190213
variableValues)}.
191214
- Return {responseStream}.
192215

193-
Note: In a large-scale subscription system, the {Subscribe()} and
194-
{ExecuteSubscriptionEvent()} algorithms may be run on separate services to
195-
maintain predictable scaling properties. See the section below on Supporting
216+
Note: In a large-scale subscription system, the {Subscription()} and
217+
{SubscriptionEvent()} algorithms may be run on separate services to maintain
218+
predictable scaling properties. See the section below on Supporting
196219
Subscriptions at Scale.
197220

198221
As an example, consider a chat application. To subscribe to new messages posted
@@ -313,8 +336,7 @@ MapSourceToResponseEvent(sourceStream, subscription, schema, variableValues):
313336
- Let {responseStream} be a new _event stream_.
314337
- When {sourceStream} emits {sourceValue}:
315338
- Let {executionResult} be the result of running
316-
{ExecuteSubscriptionEvent(subscription, schema, variableValues,
317-
sourceValue)}.
339+
{SubscriptionEvent(subscription, schema, variableValues, sourceValue)}.
318340
- If internal {error} was raised:
319341
- Cancel {sourceStream}.
320342
- Complete {responseStream} with {error}.
@@ -328,21 +350,21 @@ MapSourceToResponseEvent(sourceStream, subscription, schema, variableValues):
328350
- Complete {responseStream} normally.
329351
- Return {responseStream}.
330352

331-
Note: Since {ExecuteSubscriptionEvent()} handles all _execution error_, and
332-
_request error_ only occur during {CreateSourceEventStream()}, the only
333-
remaining error condition handled from {ExecuteSubscriptionEvent()} are internal
334-
exceptional errors not described by this specification.
353+
Note: Since {SubscriptionEvent()} handles all _execution error_, and _request
354+
error_ only occur during {CreateSourceEventStream()}, the only remaining error
355+
condition handled from {SubscriptionEvent()} are internal exceptional errors not
356+
described by this specification.
335357

336-
ExecuteSubscriptionEvent(subscription, schema, variableValues, initialValue):
358+
SubscriptionEvent(subscription, schema, variableValues, initialValue):
337359

338360
- Let {subscriptionType} be the root Subscription type in {schema}.
339361
- Assert: {subscriptionType} is an Object type.
340362
- Let {rootSelectionSet} be the _root selection set_ in {subscription}.
341363
- Return {ExecuteRootSelectionSet(variableValues, initialValue,
342364
subscriptionType, rootSelectionSet, "normal")}.
343365

344-
Note: The {ExecuteSubscriptionEvent()} algorithm is intentionally similar to
345-
{ExecuteQuery()} since this is how each event result is produced.
366+
Note: The {SubscriptionEvent()} algorithm is intentionally similar to {Query()}
367+
since this is how each event result is produced.
346368

347369
#### Unsubscribe
348370

@@ -638,7 +660,7 @@ A valid GraphQL executor can resolve the four fields in whatever order it chose
638660
(however of course `birthday` must be resolved before `month`, and `address`
639661
before `street`).
640662

641-
When executing a mutation, the selections in the top most selection set will be
663+
When performing a mutation, the selections in the top most selection set will be
642664
executed in serial order, starting with the first appearing field textually.
643665

644666
When executing a collected fields map serially, the executor must consider each
@@ -788,9 +810,9 @@ CoerceArgumentValues(objectType, field, variableValues):
788810
Any _request error_ raised as a result of input coercion during
789811
{CoerceArgumentValues()} should be treated instead as an _execution error_.
790812

791-
Note: Variable values are not coerced because they are expected to be coerced
792-
before executing the operation in {CoerceVariableValues()}, and valid operations
793-
must only allow usage of variables of appropriate types.
813+
Note: Variable values are not coerced because they are expected to be coerced by
814+
{CoerceVariableValues()} before _execution_ begins, and valid operations must
815+
only allow usage of variables of appropriate types.
794816

795817
Note: Implementations are encouraged to optimize the coercion of an argument's
796818
default value by doing so only once and caching the resulting coerced value.

0 commit comments

Comments
 (0)