Skip to content

Commit 003ed2a

Browse files
robrichardbenjieBoD
authored
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 96271da commit 003ed2a

File tree

1 file changed

+128
-2
lines changed

1 file changed

+128
-2
lines changed

spec/Section 3 -- Type System.md

Lines changed: 128 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -812,8 +812,8 @@ And will yield the subset of each object type queried:
812812
When querying an Object, the resulting mapping of fields are conceptually
813813
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
815-
that are skipped via `@skip` or `@include` directives. This ordering is
816-
correctly produced when using the {CollectFields()} algorithm.
815+
that are skipped via `@skip` or `@include` directives or postponed via `@defer`.
816+
This ordering is correctly produced when using the {CollectFields()} algorithm.
817817

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

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

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

0 commit comments

Comments
 (0)