Skip to content

Commit 99107f0

Browse files
authored
Add Response Section for defer/stream (#4)
* Add Response Section for defer/stream * review fixes * fix
1 parent fb94bc6 commit 99107f0

File tree

1 file changed

+195
-11
lines changed

1 file changed

+195
-11
lines changed

spec/Section 7 -- Response.md

Lines changed: 195 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ 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+
A response to a GraphQL request must be a map or a stream of incrementally
14+
delivered results. The response will be a stream of incrementally delivered
15+
results when the GraphQL service has deferred or streamed data as a result of
16+
the `@defer` or `@stream` directives. When the response of the GraphQL operation
17+
contains incrementally delivered results, the first value will be an initial
18+
payload, followed by one or more subsequent payloads.
1419

1520
If the request raised any errors, the response map must contain an entry with
1621
key `errors`. The value of this entry is described in the "Errors" section. If
@@ -22,14 +27,31 @@ key `data`. The value of this entry is described in the "Data" section. If the
2227
request failed before execution, due to a syntax error, missing information, or
2328
validation error, this entry must not be present.
2429

30+
When the response of the GraphQL operation contains incrementally delivered
31+
results, both the initial payload and all subsequent payloads must contain an
32+
entry with key `hasNext`. The value of this entry must be {true} for all but the
33+
last response in the stream. The value of this entry must be {false} for the
34+
last response of the stream. This entry must not be present for GraphQL
35+
operations that return a single response map.
36+
37+
When the response of the GraphQL operation contains incrementally delivered
38+
results, both the initial payload and any subsequent payloads may contain
39+
entries with the keys `pending`, `incremental`, and/or `completed`. The value of
40+
these entries are described in the "Pending", "Incremental", and "Completed"
41+
sections below.
42+
2543
The response map may also contain an entry with key `extensions`. This entry, if
2644
set, must have a map as its value. This entry is reserved for implementers to
2745
extend the protocol however they see fit, and hence there are no additional
28-
restrictions on its contents.
46+
restrictions on its contents. When the response of the GraphQL operation is a
47+
response stream, the initial payload and any subsequent payloads may contain an
48+
entry with the key `extensions`, also reserved for implementers to extend the
49+
protocol however they see fit. Additionally, implementers may send subsequent
50+
payloads containing only `hasNext` and `extensions` entries.
2951

3052
To ensure future changes to the protocol do not break existing services and
3153
clients, the top level response map must not contain any entries other than the
32-
three described above.
54+
entries described above.
3355

3456
Note: When `errors` is present in the response, it may be helpful for it to
3557
appear first when serialized to make it more clear when errors are present in a
@@ -48,6 +70,10 @@ present in the result.
4870
If an error was raised during the execution that prevented a valid response, the
4971
`data` entry in the response should be `null`.
5072

73+
When the response of the GraphQL operation contains incrementally delivered
74+
results, `data` may only be present in the initial payload. `data` must not be
75+
present in any subsequent payloads.
76+
5177
### Errors
5278

5379
The `errors` entry in the response is a non-empty list of errors raised during
@@ -107,14 +133,8 @@ syntax element.
107133
If an error can be associated to a particular field in the GraphQL result, it
108134
must contain an entry with the key `path` that details the path of the response
109135
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.
136+
`null` result is intentional or caused by a runtime error. The value of this
137+
field is described in the [Path](#sec-Path) section.
118138

119139
For example, if fetching one of the friends' names fails in the following
120140
operation:
@@ -244,6 +264,170 @@ discouraged.
244264
}
245265
```
246266

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

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

0 commit comments

Comments
 (0)