From e546aacd22b6a434546fbc400540b5bd5cda0f64 Mon Sep 17 00:00:00 2001 From: Jeff Auriemma Date: Tue, 6 Aug 2024 09:46:13 -0400 Subject: [PATCH 1/5] Add GraphQLConf 2024 banner (#1107) --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 458213632..09a7962a5 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![GraphQLConf 2024 Banner: September 10-12, San Francisco. Hosted by the GraphQL Foundation](https://github.com/user-attachments/assets/0203f10b-ae1e-4fe1-9222-6547fa2bbd5d)](https://graphql.org/conf/2024/?utm_source=github&utm_medium=graphql_spec&utm_campaign=readme) + # GraphQL GraphQL Logo From 7073e3a096c0a3fea9e605079a885d988a59d79f Mon Sep 17 00:00:00 2001 From: Yaacov Rydzinski Date: Thu, 17 Oct 2024 12:03:49 +0300 Subject: [PATCH 2/5] enhance(ResolveFieldValue): note that list items may be async (#1066) --- spec/Section 6 -- Execution.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/Section 6 -- Execution.md b/spec/Section 6 -- Execution.md index 5b8594e30..8efd401a4 100644 --- a/spec/Section 6 -- Execution.md +++ b/spec/Section 6 -- Execution.md @@ -666,7 +666,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 From df1acea882d28df22184a7c12449864b239b9dd7 Mon Sep 17 00:00:00 2001 From: Benjie Date: Thu, 21 Nov 2024 20:14:09 +0000 Subject: [PATCH 3/5] Fix coercion table for list (#1057) --- spec/Section 3 -- Type System.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index 4f9356f0c..e52519fb7 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -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` | From 34730e86a151643f51106ac1a1f35985d3da8caa Mon Sep 17 00:00:00 2001 From: Martin Bonnin Date: Thu, 5 Dec 2024 19:49:19 +0100 Subject: [PATCH 4/5] Make the reason argument in `@deprecated` non-nullable (#1040) * Make the reason argument in `@deprecated` non-nullable * update language for deprecationReason * add missing bang --- spec/Section 3 -- Type System.md | 2 +- spec/Section 4 -- Introspection.md | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/spec/Section 3 -- Type System.md b/spec/Section 3 -- Type System.md index e52519fb7..1348899fb 100644 --- a/spec/Section 3 -- Type System.md +++ b/spec/Section 3 -- Type System.md @@ -2101,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 ``` diff --git a/spec/Section 4 -- Introspection.md b/spec/Section 4 -- Introspection.md index d2ec33b6b..b260559cb 100644 --- a/spec/Section 4 -- Introspection.md +++ b/spec/Section 4 -- Introspection.md @@ -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 @@ -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 @@ -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 @@ -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 From c37a4a400e2ff61ade66c1c5947e0845a6b85c9f Mon Sep 17 00:00:00 2001 From: Lee Byron Date: Thu, 5 Dec 2024 11:23:39 -0800 Subject: [PATCH 5/5] Editorial changes for Event Streams (#1099) * Editorial changes for Event Streams This makes a few changes to the Subscriptions section where we're talking about event streams in an attempt to make it more clear about what's going on. - Revised variable names from "fieldStream" to "sourceStream" to make it easier to trace variables through algorithms. - Rewrote the "Event Streams" definition to be more clear about "emit" keyword and have clear paragraphs on completion and cancellation. - Rewrote the `MapSourceToResponseEvent` algorithm to be a correctly formatted algorithm with a return statement at the end. Introduced a new "When" keyword to describe event subscriptions. Added explicit sections on passing back cancellation (discussed in WG) as well as completion with error (not discussed, but I realized was also left ambiguous) * feedback and use definition syntax --- spec/Section 2 -- Language.md | 4 +- spec/Section 6 -- Execution.md | 73 ++++++++++++++++++++++------------ 2 files changed, 50 insertions(+), 27 deletions(-) diff --git a/spec/Section 2 -- Language.md b/spec/Section 2 -- Language.md index 2fe3a5a31..76b5fadcb 100644 --- a/spec/Section 2 -- Language.md +++ b/spec/Section 2 -- Language.md @@ -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_. diff --git a/spec/Section 6 -- Execution.md b/spec/Section 6 -- Execution.md index 8efd401a4..8be4928ae 100644 --- a/spec/Section 6 -- Execution.md +++ b/spec/Section 6 -- Execution.md @@ -164,7 +164,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". @@ -217,14 +217,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** @@ -250,8 +257,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): @@ -268,15 +275,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}. @@ -287,17 +294,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): @@ -317,9 +340,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):