Skip to content

Commit

Permalink
release: v1.22.0
Browse files Browse the repository at this point in the history
  • Loading branch information
bnjjj authored Jun 21, 2023
2 parents 065a6a6 + 637272d commit f9c48bc
Show file tree
Hide file tree
Showing 93 changed files with 7,265 additions and 289 deletions.
15 changes: 7 additions & 8 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ executors:
parameters:
toolchain_version:
type: string
default: '{{ checksum ".circleci/config.yml" }}-{{ checksum "~/.arch" }}-{{ checksum "rust-toolchain.toml" }}-{{ checksum "~/.daily_version" }}'
default: '{{ checksum ".circleci/config.yml" }}-v2-{{ checksum "~/.arch" }}-{{ checksum "rust-toolchain.toml" }}-{{ checksum "~/.daily_version" }}'
xtask_version:
type: string
default: '{{ checksum ".circleci/config.yml" }}-{{ checksum "~/.arch" }}-{{ checksum "rust-toolchain.toml" }}-{{ checksum "~/.xtask_version" }}'
Expand All @@ -91,7 +91,7 @@ parameters:
# forks of the project to run their own tests on their own CircleCI deployments with no
# additional configuration.
common_job_environment: &common_job_environment
CARGO_NET_GIT_FETCH_WITH_CLI: true
CARGO_NET_GIT_FETCH_WITH_CLI: "true"
RUST_BACKTRACE: full
CARGO_INCREMENTAL: 0
commands:
Expand All @@ -107,7 +107,7 @@ commands:
- restore_cache:
keys:
- "<< pipeline.parameters.toolchain_version >>"
- install_debian_packages:
- install_packages:
platform: << parameters.platform >>
- install_protoc:
platform: << parameters.platform >>
Expand Down Expand Up @@ -205,7 +205,7 @@ commands:
echo "${CIRCLE_PROJECT_REPONAME}-${COMMON_ANCESTOR_REF}" > ~/.merge_version
# Linux specific step to install packages that are needed
install_debian_packages:
install_packages:
parameters:
platform:
type: executor
Expand All @@ -222,11 +222,10 @@ commands:
name: Update and install dependencies
command: |
if [[ ! -d "$HOME/.deb" ]]; then
mkdir ~/.deb
mkdir $HOME/.deb
sudo apt-get --download-only -o Dir::Cache="$HOME/.deb" -o Dir::Cache::archives="$HOME/.deb" install libssl-dev libdw-dev cmake
fi
sudo dpkg -i ~/.deb/*.deb
sudo dpkg -i $HOME/.deb/*.deb
install_protoc:
parameters:
platform:
Expand Down Expand Up @@ -762,4 +761,4 @@ workflows:
branches:
ignore: /.*/
tags:
only: /v.*/
only: /v.*/
159 changes: 159 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,165 @@ All notable changes to Router will be documented in this file.

This project adheres to [Semantic Versioning v2.0.0](https://semver.org/spec/v2.0.0.html).

# [1.22.0] - 2023-06-21

## 🚀 Features

### Federated Subscriptions ([PR #3285](https://github.com/apollographql/router/pull/3285))

> ⚠️ **This is an [Enterprise feature](https://www.apollographql.com/blog/platform/evaluating-apollo-router-understanding-free-and-open-vs-commercial-features/) of the Apollo Router.** It requires an organization with a [GraphOS Enterprise plan](https://www.apollographql.com/pricing/).
>
> If your organization _doesn't_ currently have an Enterprise plan, you can test out this functionality by signing up for a free [Enterprise trial](https://www.apollographql.com/docs/graphos/org/plans/#enterprise-trials).

#### High-Level Overview

##### What are Federated Subscriptions?

This PR adds GraphQL subscription support to the Router for use with Federation. Clients can now use GraphQL subscriptions with the Router to receive realtime updates from a supergraph. With these changes, `subscription` operations are now a first-class supported feature of the Router and Federation, alongside queries and mutations.

```mermaid
flowchart LR;
client(Client);
subgraph "Your infrastructure";
router(["Apollo Router"]);
subgraphA[Products<br/>subgraph];
subgraphB[Reviews<br/>subgraph];
router---|Subscribes<br/>over WebSocket|subgraphA;
router-.-|Can query for<br/>entity fields|subgraphB;
end;
client---|Subscribes<br/>over HTTP|router;
class client secondary;
```

##### Client to Router Communication

- Apollo has designed and implemented a new open protocol for handling subscriptions called [multipart subscriptions](https://github.com/apollographql/router/blob/dev/dev-docs/multipart-subscriptions-protocol.md)
- With this new protocol clients can manage subscriptions with the Router over tried and true HTTP; WebSockets, SSE (server-sent events), etc. are not needed
- All Apollo clients ([Apollo Client web](https://www.apollographql.com/docs/react/data/subscriptions), [Apollo Kotlin](https://www.apollographql.com/docs/kotlin/essentials/subscriptions), [Apollo iOS](https://www.apollographql.com/docs/ios/fetching/subscriptions)) have been updated to support multipart subscriptions, and can be used out of the box with little to no extra configuration
- Subscription communication between clients and the Router must use the multipart subscription protocol, meaning only subscriptions over HTTP are supported at this time

##### Router to Subgraph Communication

- The Router communicates with subscription enabled subgraphs using WebSockets
- By default, the router sends subscription requests to subgraphs using the [graphql-transport-ws protocol](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md) which is implemented in the [graphql-ws](https://github.com/enisdenjo/graphql-ws) library. You can also configure it to use the [graphql-ws protocol](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md) which is implemented in the [subscriptions-transport-ws library](https://github.com/apollographql/subscriptions-transport-ws).
- Subscription ready subgraphs can be introduced to Federation and the Router as is - no additional configuration is needed on the subgraph side

##### Subscription Execution

When the Router receives a GraphQL subscription request, the generated query plan will contain an initial subscription request to the subgraph that contributed the requested subscription root field.

For example, as a result of a client sending this subscription request to the Router:

```graphql
subscription {
reviewAdded {
id
body
product {
id
name
createdBy {
name
}
}
}
}
```

The router will send this request to the `reviews` subgraph:

```graphql
subscription {
reviewAdded {
id
body
product {
id
}
}
}
```

When the `reviews` subgraph receives new data from its underlying source event stream, that data is sent back to the Router. Once received, the Router continues following the determined query plan to fetch any additional required data from other subgraphs:

Example query sent to the `products` subgraph:

```graphql
query ($representations: [_Any!]!) {
_entities(representations: $representations) {
... on Product {
name
createdBy {
__typename
email
}
}
}
}
```

Example query sent to the `users` subgraph:

```graphql
query ($representations: [_Any!]!) {
_entities(representations: $representations) {
... on User {
name
}
}
}
```

When the Router finishes running the entire query plan, the data is merged back together and returned to the requesting client over HTTP (using the multipart subscriptions protocol).

#### Configuration

Here is a configuration example:

```yaml title="router.yaml"
subscription:
mode:
passthrough:
all: # The router uses these subscription settings UNLESS overridden per-subgraph
path: /subscriptions # The path to use for subgraph subscription endpoints (Default: /ws)
subgraphs: # Overrides subscription settings for individual subgraphs
reviews: # Overrides settings for the 'reviews' subgraph
path: /ws # Overrides '/subscriptions' defined above
protocol: graphql_transport_ws # The WebSocket-based protocol to use for subscription communication (Default: graphql_ws)
```
#### Usage Reporting
Subscription use is tracked in the Router as follows:
- **Subscription registration:** The initial subscription operation sent by a client to the Router that's responsible for starting a new subscription
- **Subscription notification:** The resolution of the client subscription’s selection set in response to a subscription enabled subgraph source event
Subscription registration and notification (with operation traces and statistics) are sent to Apollo Studio for observability.
#### Advanced Features
This PR includes the following configurable performance optimizations.
#### Deduplication
- If the Router detects that a client is using the same subscription as another client (ie. a subscription with the same HTTP headers and selection set), it will avoid starting a new subscription with the requested subgraph. The Router will reuse the same open subscription instead, and will send the same source events to the new client.
- This helps reduce the number of WebSockets that need to be opened between the Router and subscription enabled subgraphs, thereby drastically reducing Router to subgraph network traffic and overall latency
- For example, if 100 clients are subscribed to the same subscription there will be 100 open HTTP connections from the clients to the Router, but only 1 open WebSocket connection from the Router to the subgraph
- Subscription deduplication between the Router and subgraphs is enabled by default (but can be disabled via the Router config file)
#### Callback Mode
- Instead of sending subscription data between a Router and subgraph over an open WebSocket, the Router can be configured to send the subgraph a callback URL that will then be used to receive all source stream events
- Subscription enabled subgraphs send source stream events (subscription updates) back to the callback URL by making HTTP POST requests
- Refer to the [callback mode documentation](https://github.com/apollographql/router/blob/dev/dev-docs/callback_protocol.md) for more details, including an explanation of the callback URL request/response payload format
- This feature is still experimental and needs to be enabled explicitly in the Router config file
By [@bnjjj](https://github.com/bnjjj) and [@o0Ignition0o](https://github.com/o0ignition0o) in https://github.com/apollographql/router/pull/3285
# [1.21.0] - 2023-06-20
## 🚀 Features
Expand Down
54 changes: 51 additions & 3 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ dependencies = [

[[package]]
name = "apollo-router"
version = "1.21.0"
version = "1.22.0"
dependencies = [
"access-json",
"anyhow",
Expand Down Expand Up @@ -317,6 +317,7 @@ dependencies = [
"graphql_client 0.11.0",
"heck 0.4.1",
"hex",
"hmac",
"http",
"http-body",
"http-serde",
Expand Down Expand Up @@ -393,6 +394,7 @@ dependencies = [
"tokio",
"tokio-rustls 0.23.4",
"tokio-stream",
"tokio-tungstenite",
"tokio-util",
"tonic 0.8.3",
"tonic-build",
Expand Down Expand Up @@ -420,7 +422,7 @@ dependencies = [

[[package]]
name = "apollo-router-benchmarks"
version = "1.21.0"
version = "1.22.0"
dependencies = [
"apollo-parser 0.4.1",
"apollo-router",
Expand All @@ -436,7 +438,7 @@ dependencies = [

[[package]]
name = "apollo-router-scaffold"
version = "1.21.0"
version = "1.22.0"
dependencies = [
"anyhow",
"cargo-scaffold",
Expand Down Expand Up @@ -645,6 +647,7 @@ checksum = "f8175979259124331c1d7bf6586ee7e0da434155e4b2d48ec2c8386281d8df39"
dependencies = [
"async-trait",
"axum-core",
"base64 0.21.2",
"bitflags",
"bytes",
"futures-util",
Expand All @@ -663,8 +666,10 @@ dependencies = [
"serde_json",
"serde_path_to_error",
"serde_urlencoded",
"sha1 0.10.5",
"sync_wrapper",
"tokio",
"tokio-tungstenite",
"tower",
"tower-layer",
"tower-service",
Expand Down Expand Up @@ -6171,6 +6176,22 @@ dependencies = [
"tokio-stream",
]

[[package]]
name = "tokio-tungstenite"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd"
dependencies = [
"futures-util",
"log",
"rustls 0.20.8",
"rustls-native-certs",
"tokio",
"tokio-rustls 0.23.4",
"tungstenite",
"webpki",
]

[[package]]
name = "tokio-util"
version = "0.7.8"
Expand Down Expand Up @@ -6510,6 +6531,27 @@ dependencies = [
"syn 1.0.109",
]

[[package]]
name = "tungstenite"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788"
dependencies = [
"base64 0.13.1",
"byteorder",
"bytes",
"http",
"httparse",
"log",
"rand 0.8.5",
"rustls 0.20.8",
"sha1 0.10.5",
"thiserror",
"url",
"utf-8",
"webpki",
]

[[package]]
name = "typed-builder"
version = "0.9.1"
Expand Down Expand Up @@ -6721,6 +6763,12 @@ dependencies = [
"url",
]

[[package]]
name = "utf-8"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"

[[package]]
name = "utf8parse"
version = "0.2.1"
Expand Down
2 changes: 1 addition & 1 deletion apollo-router-benchmarks/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "apollo-router-benchmarks"
version = "1.21.0"
version = "1.22.0"
authors = ["Apollo Graph, Inc. <[email protected]>"]
edition = "2021"
license = "Elastic-2.0"
Expand Down
2 changes: 1 addition & 1 deletion apollo-router-scaffold/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "apollo-router-scaffold"
version = "1.21.0"
version = "1.22.0"
authors = ["Apollo Graph, Inc. <[email protected]>"]
edition = "2021"
license = "Elastic-2.0"
Expand Down
2 changes: 1 addition & 1 deletion apollo-router-scaffold/templates/base/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ apollo-router = { path ="{{integration_test}}apollo-router" }
apollo-router = { git="https://github.com/apollographql/router.git", branch="{{branch}}" }
{{else}}
# Note if you update these dependencies then also update xtask/Cargo.toml
apollo-router = "1.21.0"
apollo-router = "1.22.0"
{{/if}}
{{/if}}
async-trait = "0.1.52"
Expand Down
2 changes: 1 addition & 1 deletion apollo-router-scaffold/templates/base/xtask/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ apollo-router-scaffold = { path ="{{integration_test}}apollo-router-scaffold" }
{{#if branch}}
apollo-router-scaffold = { git="https://github.com/apollographql/router.git", branch="{{branch}}" }
{{else}}
apollo-router-scaffold = { git = "https://github.com/apollographql/router.git", tag = "v1.21.0" }
apollo-router-scaffold = { git = "https://github.com/apollographql/router.git", tag = "v1.22.0" }
{{/if}}
{{/if}}
anyhow = "1.0.58"
Expand Down
Loading

0 comments on commit f9c48bc

Please sign in to comment.