Skip to content

Commit bcb92a2

Browse files
committed
Spec edits for incremental delivery, Section 7 only
1 parent 2f36b5e commit bcb92a2

File tree

1 file changed

+229
-21
lines changed

1 file changed

+229
-21
lines changed

spec/Section 7 -- Response.md

Lines changed: 229 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,74 @@ the case that any _field error_ was raised on a field and was replaced with
1010

1111
## Response Format
1212

13-
A response to a GraphQL request must be a map.
13+
The result of a GraphQL request must be either a single initial response or an
14+
incremental stream. The response will be an incremental stream when the GraphQL
15+
service has deferred or streamed data as a result of the `@defer` or `@stream`
16+
directives. When the result of the GraphQL operation is an incremental stream,
17+
the first value will be an initial response, followed by one or more subsequent
18+
responses.
19+
20+
### Initial Response
21+
22+
An initial response must be a map.
1423

1524
If the request raised any errors, the response map must contain an entry with
1625
key `errors`. The value of this entry is described in the "Errors" section. If
1726
the request completed without raising any errors, this entry must not be
1827
present.
1928

20-
If the request included execution, the response map must contain an entry with
21-
key `data`. The value of this entry is described in the "Data" section. If the
22-
request failed before execution, due to a syntax error, missing information, or
23-
validation error, this entry must not be present.
29+
If the request included execution, the initial response map must contain an
30+
entry with key `data`. The value of this entry is described in the "Data"
31+
section. If the request failed before execution, due to a syntax error, missing
32+
information, or validation error, this entry must not be present.
33+
34+
When the result of the GraphQL operation is an incremental stream, the initial
35+
response must contain an entry with key `hasNext`. The value of this entry must
36+
be {true}. This entry must not be present for GraphQL operations that result in
37+
a single initial response.
2438

25-
The response map may also contain an entry with key `extensions`. This entry, if
26-
set, must have a map as its value. This entry is reserved for implementers to
27-
extend the protocol however they see fit, and hence there are no additional
28-
restrictions on its contents.
39+
When the result of the GraphQL operation is an incremental stream, the initial
40+
response may contain entries with the keys `pending`, `incremental`, and/or
41+
`completed`. The value of these entries are described in the "Pending",
42+
"Incremental", and "Completed" sections below.
43+
44+
The initial response map may also contain an entry with key `extensions`. This
45+
entry, if set, must have a map as its value. This entry is reserved for
46+
implementers to extend the protocol however they see fit, and hence there are no
47+
additional restrictions on its contents.
2948

3049
To ensure future changes to the protocol do not break existing services and
31-
clients, the top level response map must not contain any entries other than the
32-
three described above.
50+
clients, the initial response map must not contain any entries other than the
51+
entries described above.
3352

34-
Note: When `errors` is present in the response, it may be helpful for it to
35-
appear first when serialized to make it more clear when errors are present in a
53+
Note: When `errors` is present in a response, it may be helpful for it to appear
54+
first when serialized to make it more clear when errors are present in a
3655
response during debugging.
3756

57+
### Subsequent Response
58+
59+
When the result of the GraphQL operation is an incremental stream, the first
60+
value will be an initial response, followed by one or more subsequent responses.
61+
A subsequent response must be a map.
62+
63+
Each subsequent response must contain an entry with key `hasNext`. The value of
64+
this entry must be {true} for all but the last response in the stream. The value
65+
of this entry must be {false} for the last response of the stream.
66+
67+
Each subsequent response may contain entries with the keys `pending`,
68+
`incremental`, and/or `completed`. The value of these entries are described in
69+
the "Pending", "Incremental", and "Completed" sections below.
70+
71+
The subsequent response map may also contain an entry with key `extensions`.
72+
This entry, if set, must have a map as its value. This entry is reserved for
73+
implementers to extend the protocol however they see fit, and hence there are no
74+
additional restrictions on its contents. Implementers may send subsequent
75+
responses containing only `hasNext` and `extensions` entries.
76+
77+
To ensure future changes to the protocol do not break existing services and
78+
clients, the initial response map must not contain any entries other than the
79+
entries described above.
80+
3881
### Data
3982

4083
The `data` entry in the response will be the result of the execution of the
@@ -48,6 +91,10 @@ present in the response.
4891
If an error was raised during the execution that prevented a valid response, the
4992
`data` entry in the response should be `null`.
5093

94+
When the response of the GraphQL operation is an incremental stream, `data` may
95+
only be present in the initial response. `data` must not be present in any
96+
subsequent responses.
97+
5198
### Errors
5299

53100
The `errors` entry in the response is a non-empty list of errors raised during
@@ -107,14 +154,8 @@ syntax element.
107154
If an error can be associated to a particular field in the GraphQL result, it
108155
must contain an entry with the key `path` that details the path of the response
109156
field which experienced the error. This allows clients to identify whether a
110-
`null` result is intentional or caused by a runtime error.
111-
112-
If present, this field must be a list of path segments starting at the root of
113-
the response and ending with the field associated with the error. Path segments
114-
that represent fields must be strings, and path segments that represent list
115-
indices must be 0-indexed integers. If the error happens in an aliased field,
116-
the path to the error must use the aliased name, since it represents a path in
117-
the response, not in the request.
157+
`null` result is intentional or caused by a runtime error. The value of this
158+
field is described in the [Path](#sec-Path) section.
118159

119160
For example, if fetching one of the friends' names fails in the following
120161
operation:
@@ -244,6 +285,173 @@ discouraged.
244285
}
245286
```
246287

288+
### Path
289+
290+
A `path` field allows for the association to a particular field in a GraphQL
291+
result. This field should be a list of path segments starting at the root of the
292+
response and ending with the field to be associated with. Path segments that
293+
represent fields should be strings, and path segments that represent list
294+
indices should be 0-indexed integers. If the path is associated to an aliased
295+
field, the path should use the aliased name, since it represents a path in the
296+
response, not in the request.
297+
298+
When the `path` field is present on an "Error result", it indicates the response
299+
field which experienced the error.
300+
301+
### Pending
302+
303+
The `pending` entry in the response is a non-empty list of Pending Results. If
304+
the response of the GraphQL operation is an incremental stream, this field may
305+
appear on both the initial and subsequent responses. If present, the `pending`
306+
entry must contain at least one Pending Result.
307+
308+
Each Pending Result corresponds to either a `@defer` or `@stream` directive
309+
located at a specific path in the response data. The Pending Result is used to
310+
communicate that the GraphQL service has chosen to incrementally deliver the
311+
data associated with this `@defer` or `@stream` directive and clients should
312+
expect the associated data in either the current response, or one of the
313+
following responses.
314+
315+
**Pending Result Format**
316+
317+
Every Pending Result must contain an entry with the key `id` with a string
318+
value. This `id` should be used by clients to correlate Pending Results with
319+
Completed Results. The `id` value must be unique for the entire response stream.
320+
There must not be any other Pending Result in any response that contains the
321+
same `id`.
322+
323+
Every Pending Result must contain an entry with the key `path`. When the Pending
324+
Result is associated with a `@stream` directive, it indicates the response list
325+
field that is not known to be complete. Clients should expect the GraphQL
326+
Service to incrementally deliver the remainder of indicated list field. When the
327+
Pending Result is associated with a `@defer` directive, it indicates that the
328+
response fields contained in the deferred fragment are not known to be complete.
329+
Clients should expect the GraphQL Service to incrementally deliver the remainder
330+
of the fields contained in the deferred fragment.
331+
332+
If the associated `@defer` or `@stream` directive contains a `label` argument,
333+
the Pending Result must contain an entry `label` with the value of this
334+
argument.
335+
336+
If a Pending Result is not returned for a `@defer` or `@stream` directive,
337+
clients must assume that the GraphQL service chose not to incrementally deliver
338+
this data, and the data can be found either in the `data` entry in the initial
339+
response, or one of the Incremental Results in a prior subsequent response.
340+
341+
### Incremental
342+
343+
The `incremental` entry in the response is a non-empty list of Incremental
344+
Results. If the response of the GraphQL operation is an incremental stream, this
345+
field may appear on both the initial and subsequent responses. If present, the
346+
`incremental` entry must contain at least one Incremental Result.
347+
348+
The Incremental Result is used to deliver data that the GraphQL service has
349+
chosen to incrementally deliver. An Incremental Result may be ether an
350+
Incremental List Result or an Incremental Object Result.
351+
352+
An Incremental List Result is used to deliver additional list items for a list
353+
field with a `@stream` directive.
354+
355+
An Incremental Object Result is used to deliver additional response fields that
356+
were contained in one or more fragments with a `@defer` directive.
357+
358+
**Incremental Result Format**
359+
360+
Every Incremental Result must contain an entry with the key `id` with a string
361+
value. This `id` must match the `id` that was returned in a prior Pending
362+
Result.
363+
364+
Additionally, Incremental List Results and Incremental Object Results have
365+
further requirements.
366+
367+
**Incremental List Result Format**
368+
369+
An Incremental List Result's `id` entry must match the `id` that was returned in
370+
a prior Pending Result. This Pending Result must be associated with a `@stream`
371+
directive.
372+
373+
The Incremental List Result's path can be determined using the prior Pending
374+
Result with the same `id` as this Incremental Result. The Incremental List
375+
Result's path is the same as the Pending Result's `path`.
376+
377+
Every Incremental List Result must contain an `items` entry. The `items` entry
378+
must contain a list of additional list items for the response field at the
379+
Incremental List Result's `path`. This output will be a list of the same type of
380+
the response field at this path.
381+
382+
If any field errors were raised during the execution of the results in `items`
383+
and these errors propagate to a path higher than the Incremental List Result's
384+
path, The Incremental List Result is considered failed and should not be
385+
included in the response stream. The errors that caused this failure will be
386+
included in a Completed Result.
387+
388+
If any field errors were raised during the execution of the results in `items`
389+
and these errors did not propagate to a path higher than the Incremental List
390+
Result's path, the Incremental List Result must contain an entry with key
391+
`errors` containing these field errors. The value of this entry is described in
392+
the "Errors" section.
393+
394+
**Incremental Object Result Format**
395+
396+
An Incremental Object Result's `id` entry must match the `id` that was returned
397+
in a prior Pending Result. This Pending Result must be associated with a
398+
`@defer` directive.
399+
400+
The Incremental Object Result's path can be determined using the prior Pending
401+
Result with the same `id` as this Incremental Result. The Incremental Object
402+
Result may contain a `subPath` entry. If the `subPath` entry is present, The
403+
Incremental Object Result's path can be determined by concatenating the Pending
404+
Result's `path` with this `subPath`. If no `subPath` entry is present, the path
405+
is the same as the Pending Result's `path`.
406+
407+
Every Incremental Object Result must contain a `data` entry. The `data` entry
408+
must contain a map of additional response fields. The `data` entry in an
409+
Incremental Object Result will be of the type of a particular field in the
410+
GraphQL result. The Incremental Object Result's path will contain the path
411+
segments of the field this data is associated with.
412+
413+
An Incremental Object Result's data may contain response fields that were
414+
contained in more than one deferred fragments. In that case, the `id` of the
415+
Incremental Object Result must point to the Pending Result that results in the
416+
shortest path.
417+
418+
If any field errors were raised during the execution of the results in `data`
419+
and these errors propagated to a path higher than the Incremental Object
420+
Result's path, The Incremental Object Result is considered failed and should not
421+
be included in the response stream. The errors that caused this failure will be
422+
included in a Completed Result.
423+
424+
If any field errors were raised during the execution of the results in `data`
425+
and these errors did not propagate to a path higher than the Incremental Object
426+
Result's path, the Incremental Object Result must contain an entry with key
427+
`errors` containing these field errors. The value of this entry is described in
428+
the "Errors" section.
429+
430+
### Completed
431+
432+
The `completed` entry in the response is a non-empty list of Completed Results.
433+
If the response of the GraphQL operation is an incremental stream, this field
434+
may appear on both the initial and subsequent responses. If present, the
435+
`completed` entry must contain at least one Completed Result.
436+
437+
Each Completed Result corresponds to a prior Pending Result. The Completed
438+
Result is used to communicate that the GraphQL service has completed the
439+
incremental delivery of the data associated with the corresponding Pending
440+
Result. The associated data must have been completed in the current response.
441+
442+
**Completed Result Format**
443+
444+
Every Completed Result must contain an entry with the key `id` with a string
445+
value. The `id` entry must match the `id` that was returned in a prior Pending
446+
Result.
447+
448+
A Completed Result may contain an `errors` entry. When the `errors` entry is
449+
present, it informs clients that the delivery of the data associated with the
450+
corresponding Pending Result has failed, due to an error bubbling to a path
451+
higher than the Incremental Data Result's path. The `errors` entry must contain
452+
these field errors. The value of this entry is described in the "Errors"
453+
section.
454+
247455
## Serialization Format
248456

249457
GraphQL does not require a specific serialization format. However, clients

0 commit comments

Comments
 (0)