Skip to content

Commit

Permalink
Move examples to Appendix
Browse files Browse the repository at this point in the history
  • Loading branch information
robrichard committed Nov 8, 2024
1 parent abafb76 commit 0310656
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 192 deletions.
191 changes: 191 additions & 0 deletions spec/Appendix C -- Examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
# C. Appendix: Examples

## Incremental Delivery Examples

### Example 1 - A query containing both defer and stream

```graphql example
query {
person(id: "cGVvcGxlOjE=") {
...HomeWorldFragment @defer(label: "homeWorldDefer")
name
films @stream(initialCount: 1, label: "filmsStream") {
title
}
}
}
fragment HomeWorldFragment on Person {
homeWorld {
name
}
}
```

The response stream might look like:

Payload 1, the initial response does not contain any deferred or streamed
results in the `data` entry. The initial response contains a `hasNext` entry,
indicating that subsequent payloads will be delivered. There are two Pending
Responses indicating that results for both the `@defer` and `@stream` in the
query will be delivered in the subsequent payloads.

```json example
{
"data": {
"person": {
"name": "Luke Skywalker",
"films": [{ "title": "A New Hope" }]
}
},
"pending": [
{ "id": "0", "path": ["person"], "label": "homeWorldDefer" },
{ "id": "1", "path": ["person", "films"], "label": "filmsStream" }
],
"hasNext": true
}
```

Payload 2, contains the deferred data and the first streamed list item. There is
one Completed Result, indicating that the deferred data has been completely
delivered.

```json example
{
"incremental": [
{
"id": "0",
"data": { "homeWorld": { "name": "Tatooine" } }
},
{
"id": "1",
"items": [{ "title": "The Empire Strikes Back" }]
}
],
"completed": [
{"id": "0"}
]
"hasNext": true
}
```

Payload 3, contains the final stream payload. In this example, the underlying
iterator does not close synchronously so {hasNext} is set to {true}. If this
iterator did close synchronously, {hasNext} would be set to {false} and this
would be the final response.

```json example
{
"incremental": [
{
"id": "1",
"items": [{ "title": "Return of the Jedi" }]
}
],
"hasNext": true
}
```

Payload 4, contains no incremental data. {hasNext} set to {false} indicates the
end of the response stream. This response is sent when the underlying iterator
of the `films` field closes.

```json example
{
"hasNext": false
}
```

### Example 2 - A query containing overlapping defers

```graphql example
query {
person(id: "cGVvcGxlOjE=") {
...HomeWorldFragment @defer(label: "homeWorldDefer")
...NameAndHomeWorldFragment @defer(label: "nameAndWorld")
firstName
}
}
fragment HomeWorldFragment on Person {
homeWorld {
name
terrain
}
}

fragment NameAndHomeWorldFragment on Person {
firstName
lastName
homeWorld {
name
}
}
```

The response stream might look like:

Payload 1, the initial response contains the results of the `firstName` field.
Even though it is also present in the `HomeWorldFragment`, it must be returned
in the initial payload because it is also defined outside of any fragments with
the `@defer` directive. Additionally, There are two Pending Responses indicating
that results for both `@defer`s in the query will be delivered in the subsequent
payloads.

```json example
{
"data": {
"person": {
"firstName": "Luke"
}
},
"pending": [
{ "id": "0", "path": ["person"], "label": "homeWorldDefer" },
{ "id": "1", "path": ["person"], "label": "nameAndWorld" }
],
"hasNext": true
}
```

Payload 2, contains the deferred data from `HomeWorldFragment`. There is one
Completed Result, indicating that `HomeWorldFragment` has been completely
delivered. Because the `homeWorld` field is present in two separate `@defer`s,
it is separated into its own Incremental Result.

The second Incremental Result contains the data for the `terrain` field. This
incremental result contains a `subPath` property to indicate to clients that the
path of this result can be determined by concatenating the path from the Pending
Result with id `"0"` and this `subPath` entry.

```json example
{
"incremental": [
{
"id": "0",
"data": { "homeWorld": { "name": "Tatooine" } }
},
{
"id": "0",
"subPath": ["homeWorld"],
"data": { "terrain": "desert" }
}
],
"completed": [{ "id": "0" }],
"hasNext": true
}
```

Payload 3, contains the remaining data from the `NameAndHomeWorldFragment`.
`lastName` is the only remaining field that has not been delivered in a previous
payload.

```json example
{
"incremental": [
{
"id": "1",
"data": { "lastName": "Skywalker" }
}
],
"completed": [{ "id": "1" }],
"hasNext": false
}
```
2 changes: 2 additions & 0 deletions spec/GraphQL.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,5 @@ Note: This is an example of a non-normative note.
# [Appendix: Notation Conventions](Appendix%20A%20--%20Notation%20Conventions.md)

# [Appendix: Grammar Summary](Appendix%20B%20--%20Grammar%20Summary.md)

# [Appendix: Examples](Appendix%20C%20--%20Examples.md)
192 changes: 0 additions & 192 deletions spec/Section 7 -- Response.md
Original file line number Diff line number Diff line change
Expand Up @@ -432,198 +432,6 @@ higher than the Incremental Data Result's path. The `errors` entry must contain
these field errors. The value of this entry is described in the "Errors"
section.

### Examples

#### A query containing both defer and stream:

```graphql example
query {
person(id: "cGVvcGxlOjE=") {
...HomeWorldFragment @defer(label: "homeWorldDefer")
name
films @stream(initialCount: 1, label: "filmsStream") {
title
}
}
}
fragment HomeWorldFragment on Person {
homeWorld {
name
}
}
```

The response stream might look like:

Payload 1, the initial response does not contain any deferred or streamed
results in the `data` entry. The initial response contains a `hasNext` entry,
indicating that subsequent payloads will be delivered. There are two Pending
Responses indicating that results for both the `@defer` and `@stream` in the
query will be delivered in the subsequent payloads.

```json example
{
"data": {
"person": {
"name": "Luke Skywalker",
"films": [{ "title": "A New Hope" }]
}
},
"pending": [
{ "id": "0", "path": ["person"], "label": "homeWorldDefer" },
{ "id": "1", "path": ["person", "films"], "label": "filmsStream" }
],
"hasNext": true
}
```

Payload 2, contains the deferred data and the first streamed list item. There is
one Completed Result, indicating that the deferred data has been completely
delivered.

```json example
{
"incremental": [
{
"id": "0",
"data": { "homeWorld": { "name": "Tatooine" } }
},
{
"id": "1",
"items": [{ "title": "The Empire Strikes Back" }]
}
],
"completed": [
{"id": "0"}
]
"hasNext": true
}
```

Payload 3, contains the final stream payload. In this example, the underlying
iterator does not close synchronously so {hasNext} is set to {true}. If this
iterator did close synchronously, {hasNext} would be set to {false} and this
would be the final response.

```json example
{
"incremental": [
{
"id": "1",
"items": [{ "title": "Return of the Jedi" }]
}
],
"hasNext": true
}
```

Payload 4, contains no incremental data. {hasNext} set to {false} indicates the
end of the response stream. This response is sent when the underlying iterator
of the `films` field closes.

```json example
{
"hasNext": false
}
```

### Examples

#### A query containing overlapping defers:

```graphql example
query {
person(id: "cGVvcGxlOjE=") {
...HomeWorldFragment @defer(label: "homeWorldDefer")
...NameAndHomeWorldFragment @defer(label: "nameAndWorld")
firstName
}
}
fragment HomeWorldFragment on Person {
homeWorld {
name
terrain
}
}

fragment NameAndHomeWorldFragment on Person {
firstName
lastName
homeWorld {
name
}
}
```

The response stream might look like:

Payload 1, the initial response contains the results of the `firstName` field.
Even though it is also present in the `HomeWorldFragment`, it must be returned
in the initial payload because it is also defined outside of any fragments with
the `@defer` directive. Additionally, There are two Pending Responses indicating
that results for both `@defer`s in the query will be delivered in the subsequent
payloads.

```json example
{
"data": {
"person": {
"firstName": "Luke"
}
},
"pending": [
{ "id": "0", "path": ["person"], "label": "homeWorldDefer" },
{ "id": "1", "path": ["person"], "label": "nameAndWorld" }
],
"hasNext": true
}
```

Payload 2, contains the deferred data from `HomeWorldFragment`. There is one
Completed Result, indicating that `HomeWorldFragment` has been completely
delivered. Because the `homeWorld` field is present in two separate `@defer`s,
it is separated into its own Incremental Result.

The second Incremental Result contains the data for the `terrain` field. This
incremental result contains a `subPath` property to indicate to clients that the
path of this result can be determined by concatenating the path from the Pending
Result with id `"0"` and this `subPath` entry.

```json example
{
"incremental": [
{
"id": "0",
"data": { "homeWorld": { "name": "Tatooine" } }
},
{
"id": "0",
"subPath": ["homeWorld"],
"data": { "terrain": "desert" }
}
],
"completed": [{ "id": "0" }],
"hasNext": true
}
```

Payload 3, contains the remaining data from the `NameAndHomeWorldFragment`.
`lastName` is the only remaining field that has not been delivered in a previous
payload.

```json example
{
"incremental": [
{
"id": "1",
"data": { "lastName": "Skywalker" }]
}
],
"completed": [{"id": "1"}],
"hasNext": false
}
```

## Serialization Format

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

0 comments on commit 0310656

Please sign in to comment.