Skip to content

Commit 4aa10de

Browse files
robrichardbenjieBoD
authored andcommitted
Spec edits for incremental delivery, Section 3 only (#1132)
* Spec edits for incremental delivery, Section 3 * re-order arguments * Apply suggestions from code review Co-authored-by: Benjie <benjie@jemjie.com> * Address PR feedback * Address PR feedback * Update spec/Section 3 -- Type System.md Co-authored-by: Benoit 'BoD' Lubek <BoD@JRAF.org> * Update response terminology * Use new execution result terminology * Update order of arguments on @stream * field error -> execution error * update argument order in examples * _subsequent execution result_ > _execution update result_ * Update note to normative section * fix title and link * review feedback --------- Co-authored-by: Benjie <benjie@jemjie.com> Co-authored-by: Benoit 'BoD' Lubek <BoD@JRAF.org>
1 parent bf95fc4 commit 4aa10de

1 file changed

Lines changed: 128 additions & 2 deletions

File tree

spec/Section 3 -- Type System.md

Lines changed: 128 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -813,8 +813,8 @@ And will yield the subset of each object type queried:
813813
When querying an Object, the resulting mapping of fields are conceptually
814814
ordered in the same order in which they were encountered during execution,
815815
excluding fragments for which the type does not apply and fields or fragments
816-
that are skipped via `@skip` or `@include` directives. This ordering is
817-
correctly produced when using the {CollectFields()} algorithm.
816+
that are skipped via `@skip` or `@include` directives or postponed via `@defer`.
817+
This ordering is correctly produced when using the {CollectFields()} algorithm.
818818

819819
Response serialization formats capable of representing ordered maps should
820820
maintain this ordering. Serialization formats which can only represent unordered
@@ -2086,6 +2086,15 @@ GraphQL implementations that support the type system definition language must
20862086
provide the `@deprecated` directive if representing deprecated portions of the
20872087
schema.
20882088

2089+
GraphQL implementations may provide the `@defer` and/or `@stream` directives. If
2090+
either or both of these directives are provided, they must conform to the
2091+
requirements defined in this specification.
2092+
2093+
Note: The [Directives Are Defined](#sec-Directives-Are-Defined) validation rule
2094+
ensures that GraphQL operations can only include directives available on the
2095+
schema; thus operations including `@defer` or `@stream` directives can only be
2096+
executed by a GraphQL service that supports them.
2097+
20892098
GraphQL implementations that support the type system definition language should
20902099
provide the `@specifiedBy` directive if representing custom scalar definitions.
20912100

@@ -2324,6 +2333,123 @@ input UserUniqueCondition @oneOf {
23242333
}
23252334
```
23262335

2336+
### @defer
2337+
2338+
```graphql
2339+
directive @defer(
2340+
if: Boolean! = true
2341+
label: String
2342+
) on FRAGMENT_SPREAD | INLINE_FRAGMENT
2343+
```
2344+
2345+
The `@defer` directive may be provided on a fragment spread or inline fragment
2346+
to indicate that execution of the related selection set should be deferred. When
2347+
a request includes the `@defer` directive, it may return an _incremental stream_
2348+
consisting of an _initial execution result_ containing all non-deferred data,
2349+
followed by one or more _execution update result_ including deferred data.
2350+
2351+
The `@include` and `@skip` directives take precedence over `@defer`.
2352+
2353+
```graphql example
2354+
query myQuery($shouldDefer: Boolean! = true) {
2355+
user {
2356+
name
2357+
...someFragment @defer(if: $shouldDefer, label: "someLabel")
2358+
}
2359+
}
2360+
fragment someFragment on User {
2361+
id
2362+
profile_picture {
2363+
uri
2364+
}
2365+
}
2366+
```
2367+
2368+
#### @defer Arguments
2369+
2370+
- `if: Boolean! = true` - When `true`, fragment _should_ be deferred (see
2371+
[Client Handling of `@defer`/`@stream`](#sec-Client-handling-of-defer-stream)).
2372+
When `false`, fragment must not be deferred. Defaults to `true`.
2373+
- `label: String` - An optional string literal used by GraphQL clients to
2374+
identify data in the _incremental stream_ and associate it with the
2375+
corresponding defer directive. If provided, the GraphQL service must include
2376+
this label in the corresponding _pending result_ within the _incremental
2377+
stream_. The `label` argument must be unique across all `@defer` and `@stream`
2378+
directives in the document. Variables are disallowed (via
2379+
[Defer And Stream Directive Labels Are Unique](#sec-Defer-And-Stream-Directive-Labels-Are-Unique))
2380+
because their values may not be known during validation.
2381+
2382+
### @stream
2383+
2384+
```graphql
2385+
directive @stream(
2386+
if: Boolean! = true
2387+
label: String
2388+
initialCount: Int! = 0
2389+
) on FIELD
2390+
```
2391+
2392+
The `@stream` directive may be provided for a field whose type incorporates a
2393+
`List` type modifier. The directive enables returning a partial list initially,
2394+
followed by additional items in one or more _execution update result_. If the
2395+
field type incorporates multiple `List` type modifiers, only the outermost list
2396+
is streamed.
2397+
2398+
Note: The mechanism through which items are streamed is implementation-defined
2399+
and may use technologies such as asynchronous iterators.
2400+
2401+
The `@include` and `@skip` directives take precedence over `@stream`.
2402+
2403+
```graphql example
2404+
query myQuery($shouldStream: Boolean! = true) {
2405+
user {
2406+
friends(first: 10)
2407+
@stream(if: $shouldStream, label: "friendsStream", initialCount: 5) {
2408+
name
2409+
}
2410+
}
2411+
}
2412+
```
2413+
2414+
#### @stream Arguments
2415+
2416+
- `if: Boolean! = true` - When `true`, field _should_ be streamed (see
2417+
[Client Handling of `@defer`/`@stream`](#sec-Client-handling-of-defer-stream)).
2418+
When `false`, the field must behave as if the `@stream` directive is not
2419+
presentit must not be streamed and all of the list items must be included.
2420+
Defaults to `true`.
2421+
- `label: String` - An optional string literal used by GraphQL clients to
2422+
identify data in the _incremental stream_ and associate it with the
2423+
corresponding stream directive. If provided, the GraphQL service must include
2424+
this label in the corresponding _pending result_ within the _incremental
2425+
stream_. The `label` argument must be unique across all `@defer` and `@stream`
2426+
directives in the document. Variables are disallowed (via
2427+
[Defer And Stream Directive Labels Are Unique](#sec-Defer-And-Stream-Directive-Labels-Are-Unique))
2428+
because their values may not be known during validation.
2429+
- `initialCount: Int! = 0` - The number of list items to include initially when
2430+
completing the parent selection set. If omitted, defaults to `0`. An execution
2431+
error will be raised if the value of this argument is less than `0`. When the
2432+
size of the list is greater than or equal to the value of `initialCount`, the
2433+
GraphQL service _must_ initially include at least as many list items as the
2434+
value of `initialCount` (see
2435+
[Client Handling of `@defer`/`@stream`](#sec-Client-handling-of-defer-stream)).
2436+
2437+
### Client Handling of @defer/@stream
2438+
2439+
The ability to defer and/or stream data can have a potentially significant
2440+
impact on application performance. Developers generally need clear, predictable
2441+
control over their application's performance. It is highly recommended that
2442+
GraphQL services honor the `@defer` and `@stream` directives on each execution.
2443+
However, the specification allows advanced use cases where the service can
2444+
determine that it is more performant to not defer and/or stream. Services can
2445+
make this determination on case by case basis; e.g. in a single operation, one
2446+
or more `@defer` and/or `@stream` may be acted upon while others are ignored.
2447+
Therefore, GraphQL clients _must_ be able to process a _response_ that ignores
2448+
individual `@defer` and/or `@stream` directives. This also applies to the
2449+
`initialCount` argument on the `@stream` directive. Clients must be able to
2450+
process a streamed field result that contains more initial list items than were
2451+
specified in the `initialCount` argument.
2452+
23272453
### Directive Extensions
23282454

23292455
DirectiveExtension : extend directive @ Name Directives[Const]

0 commit comments

Comments
 (0)