Skip to content

Commit

Permalink
Merge branch 'main' into benjie/incremental-common
Browse files Browse the repository at this point in the history
  • Loading branch information
benjie committed Jan 9, 2025
2 parents 60a9c35 + 2073bc8 commit a1de2dd
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 62 deletions.
4 changes: 2 additions & 2 deletions spec/Section 2 -- Language.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ There are three types of operations that GraphQL models:

- query - a read-only fetch.
- mutation - a write followed by a fetch.
- subscription - a long-lived request that fetches data in response to source
events.
- subscription - a long-lived request that fetches data in response to a
sequence of events over time.

Each operation is represented by an optional operation name and a _selection
set_.
Expand Down
54 changes: 28 additions & 26 deletions spec/Section 3 -- Type System.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ TypeSystemExtension :
- TypeExtension

Type system extensions are used to represent a GraphQL type system which has
been extended from some original type system. For example, this might be used by
been extended from some previous type system. For example, this might be used by
a local service to represent data a GraphQL client only accesses locally, or by
a GraphQL service which is itself an extension of another GraphQL service.

Expand Down Expand Up @@ -266,8 +266,8 @@ SchemaExtension :
- extend schema Directives[Const]? { RootOperationTypeDefinition+ }
- extend schema Directives[Const] [lookahead != `{`]

Schema extensions are used to represent a schema which has been extended from an
original schema. For example, this might be used by a GraphQL service which adds
Schema extensions are used to represent a schema which has been extended from a
previous schema. For example, this might be used by a GraphQL service which adds
additional operation types, or additional directives to an existing schema.

Note: Schema extensions without additional operation type definitions must not
Expand All @@ -279,7 +279,7 @@ The same limitation applies to the type definitions and extensions below.
Schema extensions have the potential to be invalid if incorrectly defined.

1. The Schema must already be defined.
2. Any non-repeatable directives provided must not already apply to the original
2. Any non-repeatable directives provided must not already apply to the previous
Schema.

## Types
Expand Down Expand Up @@ -377,7 +377,7 @@ TypeExtension :
- InputObjectTypeExtension

Type extensions are used to represent a GraphQL type which has been extended
from some original type. For example, this might be used by a local service to
from some previous type. For example, this might be used by a local service to
represent additional fields a GraphQL client only accesses locally.

## Scalars
Expand Down Expand Up @@ -640,15 +640,15 @@ ScalarTypeExtension :
- extend scalar Name Directives[Const]

Scalar type extensions are used to represent a scalar type which has been
extended from some original scalar type. For example, this might be used by a
extended from some previous scalar type. For example, this might be used by a
GraphQL tool or service which adds directives to an existing scalar.

**Type Validation**

Scalar type extensions have the potential to be invalid if incorrectly defined.

1. The named type must already be defined and must be a Scalar type.
2. Any non-repeatable directives provided must not already apply to the original
2. Any non-repeatable directives provided must not already apply to the previous
Scalar type.

## Objects
Expand Down Expand Up @@ -1048,7 +1048,7 @@ ObjectTypeExtension :
- extend type Name ImplementsInterfaces [lookahead != `{`]

Object type extensions are used to represent a type which has been extended from
some original type. For example, this might be used to represent local data, or
some previous type. For example, this might be used to represent local data, or
by a GraphQL service which is itself an extension of another GraphQL service.

In this example, a local data field is added to a `Story` type:
Expand Down Expand Up @@ -1076,10 +1076,10 @@ Object type extensions have the potential to be invalid if incorrectly defined.
2. The fields of an Object type extension must have unique names; no two fields
may share the same name.
3. Any fields of an Object type extension must not be already defined on the
original Object type.
4. Any non-repeatable directives provided must not already apply to the original
previous Object type.
4. Any non-repeatable directives provided must not already apply to the previous
Object type.
5. Any interfaces provided must not be already implemented by the original
5. Any interfaces provided must not be already implemented by the previous
Object type.
6. The resulting extended object type must be a super-set of all interfaces it
implements.
Expand Down Expand Up @@ -1288,7 +1288,7 @@ InterfaceTypeExtension :
- extend interface Name ImplementsInterfaces [lookahead != `{`]

Interface type extensions are used to represent an interface which has been
extended from some original interface. For example, this might be used to
extended from some previous interface. For example, this might be used to
represent common local data on many types, or by a GraphQL service which is
itself an extension of another GraphQL service.

Expand Down Expand Up @@ -1328,11 +1328,11 @@ defined.
2. The fields of an Interface type extension must have unique names; no two
fields may share the same name.
3. Any fields of an Interface type extension must not be already defined on the
original Interface type.
4. Any Object or Interface type which implemented the original Interface type
previous Interface type.
4. Any Object or Interface type which implemented the previous Interface type
must also be a super-set of the fields of the Interface type extension (which
may be due to Object type extension).
5. Any non-repeatable directives provided must not already apply to the original
5. Any non-repeatable directives provided must not already apply to the previous
Interface type.
6. The resulting extended Interface type must be a super-set of all Interfaces
it implements.
Expand Down Expand Up @@ -1443,7 +1443,7 @@ UnionTypeExtension :
- extend union Name Directives[Const]

Union type extensions are used to represent a union type which has been extended
from some original union type. For example, this might be used to represent
from some previous union type. For example, this might be used to represent
additional local data, or by a GraphQL service which is itself an extension of
another GraphQL service.

Expand All @@ -1457,8 +1457,8 @@ Union type extensions have the potential to be invalid if incorrectly defined.
Similarly, wrapping types must not be member types of a Union.
3. All member types of a Union type extension must be unique.
4. All member types of a Union type extension must not already be a member of
the original Union type.
5. Any non-repeatable directives provided must not already apply to the original
the previous Union type.
5. Any non-repeatable directives provided must not already apply to the previous
Union type.

## Enums
Expand Down Expand Up @@ -1520,7 +1520,7 @@ EnumTypeExtension :
- extend enum Name Directives[Const] [lookahead != `{`]

Enum type extensions are used to represent an enum type which has been extended
from some original enum type. For example, this might be used to represent
from some previous enum type. For example, this might be used to represent
additional local data, or by a GraphQL service which is itself an extension of
another GraphQL service.

Expand All @@ -1531,8 +1531,8 @@ Enum type extensions have the potential to be invalid if incorrectly defined.
1. The named type must already be defined and must be an Enum type.
2. All values of an Enum type extension must be unique.
3. All values of an Enum type extension must not already be a value of the
original Enum.
4. Any non-repeatable directives provided must not already apply to the original
previous Enum.
4. Any non-repeatable directives provided must not already apply to the previous
Enum type.

## Input Objects
Expand Down Expand Up @@ -1712,7 +1712,7 @@ InputObjectTypeExtension :
- extend input Name Directives[Const] [lookahead != `{`]

Input object type extensions are used to represent an input object type which
has been extended from some original input object type. For example, this might
has been extended from some previous input object type. For example, this might
be used by a GraphQL service which is itself an extension of another GraphQL
service.

Expand All @@ -1724,8 +1724,8 @@ defined.
1. The named type must already be defined and must be a Input Object type.
2. All fields of an Input Object type extension must have unique names.
3. All fields of an Input Object type extension must not already be a field of
the original Input Object.
4. Any non-repeatable directives provided must not already apply to the original
the previous Input Object.
4. Any non-repeatable directives provided must not already apply to the previous
Input Object type.

## List
Expand Down Expand Up @@ -1780,7 +1780,9 @@ Following are examples of input coercion with various list types and values:
| `[Int]` | `1` | `[1]` |
| `[Int]` | `null` | `null` |
| `[[Int]]` | `[[1], [2, 3]]` | `[[1], [2, 3]]` |
| `[[Int]]` | `[1, 2, 3]` | Error: Incorrect item value |
| `[[Int]]` | `[1, 2, 3]` | `[[1], [2], [3]]` |
| `[[Int]]` | `[1, null, 3]` | `[[1], null, [3]]` |
| `[[Int]]` | `[[1], ["b"]]` | Error: Incorrect item value |
| `[[Int]]` | `1` | `[[1]]` |
| `[[Int]]` | `null` | `null` |

Expand Down Expand Up @@ -2099,7 +2101,7 @@ condition is false.

```graphql
directive @deprecated(
reason: String = "No longer supported"
reason: String! = "No longer supported"
) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | ENUM_VALUE
```

Expand Down
13 changes: 7 additions & 6 deletions spec/Section 4 -- Introspection.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ CommonMark-compliant Markdown renderer.

To support the management of backwards compatibility, GraphQL fields, arguments,
input fields, and enum values can indicate whether or not they are deprecated
(`isDeprecated: Boolean`) along with a description of why it is deprecated
(`isDeprecated: Boolean!`) along with a description of why it is deprecated
(`deprecationReason: String`).

Tools built using GraphQL introspection should respect deprecation by
Expand Down Expand Up @@ -424,7 +424,8 @@ Fields\:
this field.
- `isDeprecated` returns {true} if this field should no longer be used,
otherwise {false}.
- `deprecationReason` optionally provides a reason why this field is deprecated.
- `deprecationReason` returns the reason why this field is deprecated, or null
if this field is not deprecated.

### The \_\_InputValue Type

Expand All @@ -442,8 +443,8 @@ Fields\:
provided at runtime. If this input value has no default value, returns {null}.
- `isDeprecated` returns {true} if this input field or argument should no longer
be used, otherwise {false}.
- `deprecationReason` optionally provides a reason why this input field or
argument is deprecated.
- `deprecationReason` returns the reason why this input field or argument is
deprecated, or null if the input field or argument is not deprecated.

### The \_\_EnumValue Type

Expand All @@ -455,8 +456,8 @@ Fields\:
- `description` may return a String or {null}.
- `isDeprecated` returns {true} if this enum value should no longer be used,
otherwise {false}.
- `deprecationReason` optionally provides a reason why this enum value is
deprecated.
- `deprecationReason` returns the reason why this enum value is deprecated, or
null if the enum value is not deprecated.

### The \_\_Directive Type

Expand Down
76 changes: 50 additions & 26 deletions spec/Section 6 -- Execution.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ ExecuteMutation(mutation, schema, variableValues, initialValue):

### Subscription

If the operation is a subscription, the result is an event stream called the
If the operation is a subscription, the result is an _event stream_ called the
"Response Stream" where each event in the event stream is the result of
executing the operation for each new event on an underlying "Source Stream".

Expand Down Expand Up @@ -210,14 +210,21 @@ chat room ID is the "topic" and each "publish" contains the sender and text.

**Event Streams**

An event stream represents a sequence of discrete events over time which can be
observed. As an example, a "Pub-Sub" system may produce an event stream when
"subscribing to a topic", with an event occurring on that event stream for each
"publish" to that topic. Event streams may produce an infinite sequence of
events or may complete at any point. Event streams may complete in response to
an error or simply because no more events will occur. An observer may at any
point decide to stop observing an event stream by cancelling it, after which it
must receive no more events from that event stream.
:: An _event stream_ represents a sequence of events: discrete emitted values
over time which can be observed. As an example, a "Pub-Sub" system may produce
an _event stream_ when "subscribing to a topic", with an value emitted for each
"publish" to that topic.

An _event stream_ may complete at any point, often because no further events
will occur. An _event stream_ may emit an infinite sequence of values, in which
it may never complete. If an _event stream_ encounters an error, it must
complete with that error.

An observer may at any point decide to stop observing an _event stream_ by
cancelling it. When an _event stream_ is cancelled, it must complete.

Internal user code also may cancel an _event stream_ for any reason, which would
be observed as that _event stream_ completing.

**Supporting Subscriptions at Scale**

Expand All @@ -243,8 +250,8 @@ service details should be chosen by the implementing service.

#### Source Stream

A Source Stream represents the sequence of events, each of which will trigger a
GraphQL execution corresponding to that event. Like field value resolution, the
A Source Stream is an _event stream_ representing a sequence of root values,
each of which will trigger a GraphQL execution. Like field value resolution, the
logic to create a Source Stream is application-specific.

CreateSourceEventStream(subscription, schema, variableValues, initialValue):
Expand All @@ -261,15 +268,15 @@ CreateSourceEventStream(subscription, schema, variableValues, initialValue):
- Let {field} be the first entry in {fields}.
- Let {argumentValues} be the result of {CoerceArgumentValues(subscriptionType,
field, variableValues)}.
- Let {fieldStream} be the result of running
- Let {sourceStream} be the result of running
{ResolveFieldEventStream(subscriptionType, initialValue, fieldName,
argumentValues)}.
- Return {fieldStream}.
- Return {sourceStream}.

ResolveFieldEventStream(subscriptionType, rootValue, fieldName, argumentValues):

- Let {resolver} be the internal function provided by {subscriptionType} for
determining the resolved event stream of a subscription field named
determining the resolved _event stream_ of a subscription field named
{fieldName}.
- Return the result of calling {resolver}, providing {rootValue} and
{argumentValues}.
Expand All @@ -280,17 +287,33 @@ operation type.

#### Response Stream

Each event in the underlying Source Stream triggers execution of the
subscription _selection set_ using that event as a root value.
Each event from the underlying Source Stream triggers execution of the
subscription _selection set_ using that event's value as the {initialValue}.

MapSourceToResponseEvent(sourceStream, subscription, schema, variableValues):

- Return a new event stream {responseStream} which yields events as follows:
- For each {event} on {sourceStream}:
- Let {response} be the result of running
{ExecuteSubscriptionEvent(subscription, schema, variableValues, event)}.
- Yield an event containing {response}.
- When {sourceStream} completes: complete {responseStream}.
- Let {responseStream} be a new _event stream_.
- When {sourceStream} emits {sourceValue}:
- Let {response} be the result of running
{ExecuteSubscriptionEvent(subscription, schema, variableValues,
sourceValue)}.
- If internal {error} was raised:
- Cancel {sourceStream}.
- Complete {responseStream} with {error}.
- Otherwise emit {response} on {responseStream}.
- When {sourceStream} completes normally:
- Complete {responseStream} normally.
- When {sourceStream} completes with {error}:
- Complete {responseStream} with {error}.
- When {responseStream} is cancelled:
- Cancel {sourceStream}.
- Complete {responseStream} normally.
- Return {responseStream}.

Note: Since {ExecuteSubscriptionEvent()} handles all _field error_, and _request
error_ only occur during {CreateSourceEventStream()}, the only remaining error
condition handled from {ExecuteSubscriptionEvent()} are internal exceptional
errors not described by this specification.

ExecuteSubscriptionEvent(subscription, schema, variableValues, initialValue):

Expand All @@ -306,9 +329,9 @@ Note: The {ExecuteSubscriptionEvent()} algorithm is intentionally similar to
#### Unsubscribe

Unsubscribe cancels the Response Stream when a client no longer wishes to
receive payloads for a subscription. This may in turn also cancel the Source
Stream. This is also a good opportunity to clean up any other resources used by
the subscription.
receive payloads for a subscription. This in turn also cancels the Source
Stream, which is a good opportunity to clean up any other resources used by the
subscription.

Unsubscribe(responseStream):

Expand Down Expand Up @@ -679,7 +702,8 @@ ResolveFieldValue(objectType, objectValue, fieldName, argumentValues):
Note: It is common for {resolver} to be asynchronous due to relying on reading
an underlying database or networked service to produce a value. This
necessitates the rest of a GraphQL executor to handle an asynchronous execution
flow.
flow. If the field is of a list type, each value in the collection of values
returned by {resolver} may itself be retrieved asynchronously.

### Value Completion

Expand Down
4 changes: 2 additions & 2 deletions spec/Section 7 -- Response.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ of the query root operation type; if the operation was a mutation, this output
will be an object of the mutation root operation type.

If an error was raised before execution begins, the `data` entry should not be
present in the result.
present in the response.

If an error was raised during the execution that prevented a valid response, the
`data` entry in the response should be `null`.
Expand All @@ -56,7 +56,7 @@ format below.

If present, the `errors` entry in the response must contain at least one error.
If no errors were raised during the request, the `errors` entry must not be
present in the result.
present in the response.

If the `data` entry in the response is not present, the `errors` entry must be
present. It must contain at least one _request error_ indicating why no data was
Expand Down

0 comments on commit a1de2dd

Please sign in to comment.