Skip to content

Commit 30bc97f

Browse files
committed
Spec edits for incremental delivery, Section 7 only
1 parent 0701e5b commit 30bc97f

File tree

2 files changed

+257
-36
lines changed

2 files changed

+257
-36
lines changed

spec/Appendix E -- Examples.md

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ fragment HomeWorldFragment on Person {
2121
}
2222
```
2323

24-
The incremental stream might look like:
24+
The _incremental stream_ might look like:
2525

26-
The initial response does not contain any deferred or streamed results in the
27-
`data` entry. The initial response contains a `hasNext` entry, indicating that
28-
subsequent responses will be delivered. There are two Pending Results indicating
29-
that results for both the `@defer` and `@stream` in the query will be delivered
30-
in the subsequent responses.
26+
The _initial execution result_ does not contain any deferred or streamed results
27+
in the {"data"} entry. The initial execution result contains a {"hasNext"}
28+
entry, indicating that _execution update result_ will be delivered. There are
29+
two _pending result_ indicating that results for both the `@defer` and `@stream`
30+
in the query will be delivered in the execution update results.
3131

3232
```json example
3333
{
@@ -45,9 +45,9 @@ in the subsequent responses.
4545
}
4646
```
4747

48-
Subsequent response 1, contains the deferred data and the first streamed list
49-
item. There is one Completed Result, indicating that the deferred data has been
50-
completely delivered.
48+
_Execution update result_ 1 contains the deferred data and the first streamed
49+
list item. There is one _completed result_, indicating that the deferred data
50+
has been completely delivered.
5151

5252
```json example
5353
{
@@ -68,10 +68,10 @@ completely delivered.
6868
}
6969
```
7070

71-
Subsequent response 2, contains the final stream results. In this example, the
72-
underlying iterator does not close synchronously so {hasNext} is set to {true}.
73-
If this iterator did close synchronously, {hasNext} would be set to {false} and
74-
this would be the final response.
71+
_Execution update result_ 2 contains the final stream results. In this example,
72+
the underlying iterator does not close synchronously so {"hasNext"} is set to
73+
{true}. If this iterator did close synchronously, {"hasNext"} would be set to
74+
{false} and this would be the final execution update result.
7575

7676
```json example
7777
{
@@ -85,9 +85,9 @@ this would be the final response.
8585
}
8686
```
8787

88-
Subsequent response 3, contains no incremental data. {hasNext} set to {false}
89-
indicates the end of the incremental stream. This response is sent when the
90-
underlying iterator of the `films` field closes.
88+
_Execution update result_ 3 contains no incremental data. {"hasNext"} set to
89+
{false} indicates the end of the _incremental stream_. This response is sent
90+
when the underlying iterator of the `films` field closes.
9191

9292
```json example
9393
{
@@ -121,14 +121,14 @@ fragment NameAndHomeWorldFragment on Person {
121121
}
122122
```
123123

124-
The incremental stream might look like:
124+
The _incremental stream_ might look like:
125125

126-
The initial response contains the results of the `firstName` field. Even though
127-
it is also present in the `HomeWorldFragment`, it must be returned in the
128-
initial response because it is also defined outside of any fragments with the
129-
`@defer` directive. Additionally, There are two Pending Results indicating that
130-
results for both `@defer`s in the query will be delivered in the subsequent
131-
responses.
126+
The _initial execution result_ contains the results of the `firstName` field.
127+
Even though it is also present in the `HomeWorldFragment`, it must be returned
128+
in the initial response because it is also defined outside of any fragments with
129+
the `@defer` directive. Additionally, There are two _pending result_ indicating
130+
that results for both `@defer`s in the query will be delivered in the execution
131+
update results.
132132

133133
```json example
134134
{
@@ -145,15 +145,15 @@ responses.
145145
}
146146
```
147147

148-
Subsequent response 1, contains the deferred data from `HomeWorldFragment`.
148+
_Execution update result_ 1 contains the deferred data from `HomeWorldFragment`.
149149
There is one Completed Result, indicating that `HomeWorldFragment` has been
150150
completely delivered. Because the `homeWorld` field is present in two separate
151-
`@defer`s, it is separated into its own Incremental Result.
151+
`@defer`s, it is separated into its own _incremental result_.
152152

153-
The second Incremental Result contains the data for the `terrain` field. This
154-
incremental result contains a `subPath` property to indicate to clients that the
155-
path of this result can be determined by concatenating the path from the Pending
156-
Result with id `"0"` and this `subPath` entry.
153+
The second _incremental result_ contains the data for the `terrain` field. This
154+
_incremental result_ contains a {"subPath"} entry to indicate to clients that
155+
the path of this result can be determined by concatenating the path from the
156+
_pending result_ with id `"0"` and this {"subPath"} entry.
157157

158158
```json example
159159
{
@@ -173,7 +173,7 @@ Result with id `"0"` and this `subPath` entry.
173173
}
174174
```
175175

176-
Subsequent response 2, contains the remaining data from the
176+
_Execution update result_ 2 contains the remaining data from the
177177
`NameAndHomeWorldFragment`. `lastName` is the only remaining field that has not
178178
been delivered in a previous response.
179179

spec/Section 7 -- Response.md

Lines changed: 227 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ the case that any _execution error_ was raised and replaced with {null}.
1010
## Response Format
1111

1212
:: A GraphQL request returns a _response_. A _response_ is either an _execution
13-
result_, a _response stream_, or a _request error result_.
13+
result_, a _response stream_, an _incremental stream_, or a _request error
14+
result_.
1415

1516
### Execution Result
1617

@@ -43,6 +44,14 @@ value of this entry is described in the "Extensions" section.
4344
subscription and the request included execution. A response stream must be a
4445
stream of _execution result_.
4546

47+
### Incremental Stream
48+
49+
:: A GraphQL request returns an _incremental stream_ when the GraphQL service
50+
has deferred or streamed data as a result of the `@defer` or `@stream`
51+
directives. When the result of the GraphQL operation is an incremental stream,
52+
the first value will be an _initial execution result_, followed by one or more
53+
_execution update result_.
54+
4655
### Request Error Result
4756

4857
:: A GraphQL request returns a _request error result_ when one or more _request
@@ -70,6 +79,59 @@ The _request error result_ map must not contain an entry with key {"data"}.
7079
The _request error result_ map may also contain an entry with key `extensions`.
7180
The value of this entry is described in the "Extensions" section.
7281

82+
### Initial Execution Result
83+
84+
:: An _initial execution result_ is the first value yielded by an _incremental
85+
stream_.
86+
87+
An _initial execution result_ must be a map.
88+
89+
The _initial execution result_ must contain an entry with key {"data"}, and may
90+
contain entries with keys {"errors"} and {"extensions"}. The value of these
91+
entries are defined in the same way as an _execution result_ as described in the
92+
"Data", "Errors", and "Extensions" sections below.
93+
94+
The _initial execution result_ must contain an entry with the key {"hasNext"}.
95+
The value of this entry must be {true}.
96+
97+
The _initial execution result_ may contain an entry with the key {"pending"}.
98+
The value of this entry must be a non-empty list of _pending result_. Each
99+
_pending result_ must be a map as described in the "Pending Result" section
100+
below.
101+
102+
The _initial execution result_ may contain an entry with they key
103+
{"incremental"}. The value of this entry must be a non-empty list of
104+
_incremental result_. Each _incremental result_ must be a map as described in
105+
the "Incremental Result" section below.
106+
107+
The _initial execution result_ may contain an entry with they key {"completed"}.
108+
The value of this entry must be a non-empty list of _completed result_. Each
109+
_completed result_ must be a map as described in the "Completed Result" section
110+
below.
111+
112+
### Execution Update Result
113+
114+
:: An _execution update result_ is the value yielded by an _incremental stream_
115+
for all values except the first.
116+
117+
An _execution update result_ must be a map.
118+
119+
Unlike the _initial execution result_, an _execution update result_ must not
120+
contain entries with keys {"data"} or {"errors"}.
121+
122+
An _execution update result_ may contain an entry with the key {"extensions"}.
123+
The value of this entry is described in the "Extensions" section.
124+
125+
An _execution update result_ must contain an entry with the key {"hasNext"}. The
126+
value of this entry must be {true} for all but the last response in the
127+
_incremental stream_. The value of this entry must be {false} for the last
128+
response of the incremental stream.
129+
130+
The _initial execution result_ may contain entries with keys {"pending"},
131+
{"incremental"}, and/or {"completed"}. The value of these entries are defined in
132+
the same way as an _initial execution result_ as described in the "Pending
133+
Result", "Incremental Result", and "Completed Result" sections below.
134+
73135
### Response Position
74136

75137
<a name="sec-Path">
@@ -94,6 +156,9 @@ represents a path in the response, not in the request.
94156
When a _response path_ is present on an _error result_, it identifies the
95157
_response position_ which raised the error.
96158

159+
When a _response path_ is present on an _incremental result_, it identifies the
160+
_response position_ of the incremental data update.
161+
97162
A single field execution may result in multiple response positions. For example,
98163

99164
```graphql example
@@ -323,15 +388,171 @@ discouraged.
323388

324389
### Extensions
325390

326-
The {"extensions"} entry in an _execution result_ or _request error result_, if
327-
set, must have a map as its value. This entry is reserved for implementers to
328-
extend the protocol however they see fit, and hence there are no additional
329-
restrictions on its contents.
391+
The {"extensions"} entry in an _execution result_, _request error result_,
392+
_initial execution result_, or a _execution update result_, if set, must have a
393+
map as its value. This entry is reserved for implementers to extend the protocol
394+
however they see fit, and hence there are no additional restrictions on its
395+
contents.
396+
397+
### Pending Result
398+
399+
:: A _pending result_ is used to communicate to clients that the GraphQL service
400+
has chosen to incrementally deliver data associated with a `@defer` or `@stream`
401+
directive. Each pending result corresponds to a specific `@defer` or `@stream`
402+
directive located at a _response position_ in the response data. The presence of
403+
a pending result indicates that clients should expect the associated data in
404+
either the current response, or one of the following responses.
405+
406+
**Pending Result Format**
407+
408+
A _pending result_ must be a map.
409+
410+
Every _pending result_ must contain an entry with the key {"id"} with a string
411+
value. This {"id"} should be used by clients to correlate pending results with
412+
_incremental result_ and _completed result_. The {"id"} value must be unique for
413+
the entire _incremental stream_ response. There must not be any other pending
414+
result in the _incremental stream_ that contains the same {"id"}.
415+
416+
Every _pending result_ must contain an entry with the key {"path"}. When the
417+
pending result is associated with a `@stream` directive, it indicates the list
418+
at this _response position_ is not known to be complete. Clients should expect
419+
the GraphQL Service to incrementally deliver the remainder list items of this
420+
list. When the pending result is associated with a `@defer` directive, it
421+
indicates that the response fields contained in the deferred fragment are not
422+
known to be complete. Clients should expect the GraphQL Service to incrementally
423+
deliver the remainder of the fields contained in the deferred fragment at this
424+
_response position_.
425+
426+
If the associated `@defer` or `@stream` directive contains a `label` argument,
427+
the pending result must contain an entry {"label"} with the value of this
428+
argument. Clients should use this entry to differentiate the _pending results_
429+
for different deferred fragments at the same _response position_.
430+
431+
If a pending result is not returned for a `@defer` or `@stream` directive,
432+
clients must assume that the GraphQL service chose not to incrementally deliver
433+
this data, and the data can be found either in the {"data"} entry in the
434+
_initial execution result_, or one of the prior _execution update result_ in the
435+
_incremental stream_.
436+
437+
:: The _associated pending result_ is a specific _pending result_ associated
438+
with any given _incremental result_ or _completed result_. The associated
439+
pending result can be determined by finding the pending result where the value
440+
of its {"id"} entry is the same value of the {"id"} entry of the given
441+
incremental result or completed result. The associated pending result must
442+
appear in the _incremental stream_, in the same or prior _initial execution
443+
result_ or _execution update result_ as the given incremental result or
444+
completed result.
445+
446+
### Incremental Result
447+
448+
:: The _incremental result_ is used to deliver data that the GraphQL service has
449+
chosen to incrementally deliver. An incremental result may be ether an
450+
_incremental list result_ or an _incremental object result_.
451+
452+
An _incremental result_ must be a map.
453+
454+
Every _incremental result_ must contain an entry with the key {"id"} with a
455+
string value. The definition of _associated pending result_ describes how this
456+
value is used to determine the associated pending result for a given
457+
_incremental result_.
458+
459+
#### Incremental List Result
460+
461+
:: An _incremental list result_ is a _incremental result_ used to deliver
462+
additional list items for a list field with a `@stream` directive. The
463+
_associated pending result_ for this _incremental list result_ must be
464+
associated with a `@stream` directive.
465+
466+
The _response position_ for an _incremental list result_ is the {"path"} entry
467+
from its _associated pending result_.
468+
469+
**Incremental List Result Format**
470+
471+
Every _incremental list result_ must contain an entry with the key {"id"}, used
472+
to determine the _associated pending result_ for this _incremental result_.
473+
474+
Every _incremental list result_ must contain an {"items"} entry. The {"items"}
475+
entry must contain a list of additional list items for the list field in the
476+
incremental list result's _response position_. The value of this entry must be a
477+
list of the same type of the response field at this _response position_.
478+
479+
If any _execution error_ were raised during the execution of the results in
480+
{"items"} and these errors propagate to a _response position_ higher than the
481+
_incremental list result_'s response position, The incremental list result is
482+
considered failed and should not be included in the _incremental stream_. The
483+
errors that caused this failure will be included in a _completed result_.
484+
485+
If any _execution error_ were raised during the execution of the results in
486+
{"items"} and these errors did not propagate to a path higher than the
487+
_incremental list result_'s path, the incremental list result must contain an
488+
entry with key {"errors"} containing these execution errors. The value of this
489+
entry is described in the "Errors" section.
490+
491+
#### Incremental Object Result
492+
493+
:: An _incremental object result_ is a _incremental result_ used to deliver
494+
additional response fields that were contained in one or more fragments with a
495+
`@defer` directive. The _associated pending result_ for this _incremental object
496+
result_ must be associated with a `@defer` directive.
497+
498+
**Incremental Object Result Format**
499+
500+
The _incremental object result_ may contain a {"subPath"} entry. If this entry
501+
is present, The incremental object result's _response position_ can be
502+
determined by concatenating the value of the _associated pending result_'s
503+
{"path"} entry with the value of this {"subPath"} entry. If no {"subPath"} entry
504+
is present, the _response position_ is the value of the associated pending
505+
result's {"path"} entry.
506+
507+
An _incremental object result_ may be used to deliver data for response fields
508+
that were contained in more than one deferred fragments. In that case, the
509+
_associated pending result_ of the incremental object result must be a _pending
510+
result_ with the longest {"path"}.
511+
512+
Every _incremental object result_ must contain a {"data"} entry. The {"data"}
513+
entry must contain a map of additional response fields. The {"data"} entry in an
514+
incremental object result will be of the type of the field at the incremental
515+
object result's _response position_.
516+
517+
If any _execution error_ were raised during the execution of the results in
518+
{"data"} and these errors propagated to a _response position_ higher than the
519+
_incremental object result_'s response position, The incremental object result
520+
is considered failed and should not be included in the incremental stream. The
521+
errors that caused this failure will be included in a _completed result_.
522+
523+
If any _execution error_ were raised during the execution of the results in
524+
{"data"} and these errors did not propagate to a _response position_ higher than
525+
the _incremental object result_'s response position, the incremental object
526+
result must contain an entry with key {"errors"} containing these execution
527+
errors. The value of this entry is described in the "Errors" section.
528+
529+
### Completed Result
530+
531+
:: A _completed result_ is used to communicate that the GraphQL service has
532+
completed the incremental delivery of the data associated with the _associated
533+
pending result_. The corresponding data must have been completed in the same
534+
_initial execution result_ or _execution update result_ in which this completed
535+
result appears.
536+
537+
**Completed Result Format**
538+
539+
A _completed result_ must be a map.
540+
541+
Every _completed result_ must contain an entry with the key {"id"} with a string
542+
value. The definition of _associated pending result_ describes how this value is
543+
used to determine the associated pending result for a given _completed result_.
544+
545+
A _completed result_ may contain an {"errors"} entry. When the {"errors"} entry
546+
is present, it informs clients that the delivery of the data from the
547+
_associated pending result_ has failed, due to an execution error propagating to
548+
a _response position_ higher than the _incremental result_'s response position.
549+
The {"errors"} entry must contain these execution errors. The value of this
550+
entry is described in the "Errors" section.
330551

331552
### Additional Entries
332553

333554
To ensure future changes to the protocol do not break existing services and
334-
clients, the _execution result_ and _request error result_ maps must not contain
555+
clients, any of the maps described in the "Response" section must not contain
335556
any entries other than those described above. Clients must ignore any entries
336557
other than those described above.
337558

0 commit comments

Comments
 (0)