Skip to content

Commit

Permalink
Port to apollo-compiler 1.0 beta (#4038)
Browse files Browse the repository at this point in the history
Fixes #2710

# apollo-compiler background

The public API of apollo-compiler 1.0 is almost completely different
from 0.x. Notably it doesn’t have compiler objects anymore. Instead,
users mainly manipulate:

* `apollo_compiler::ast::Document` is the result of parsing one input
file/string. May contain parse errors. Finding anything requires a
linear scan of a `Vec` of top-level definitions.
* `apollo_compiler::Schema` has stuff indexed by name, with GraphQL
extensions "applied". Conversion from AST may record "build errors"
(e.g. for a name collision). Stuff with errors (e.g. that second
definition with the same name) may be missing in the main data
structure.
* `apollo_compiler::ExecutableDocument` similarly has operations and
fragments indexed by name, has build errors, and may be missing stuff
related to errors. Creating one requires `&Schema`, where it’ll find a
field definition to associate with every field selection, and resolve
the type of every selection set.

`Schema` and `ExecutableDocument` have `validate` methods to run full
GraphQL spec validation, but it needs to be called explicitly. A future
beta will likely change the API to make it less easy to forget dealing
with build errors or validation errors.

# This PR

Instead of creating and passing around a `Arc<Mutex<ApolloCompiler>>`
for every GraphQL request, the Router now creates a
`Arc<ParsedDocument>` which contains *both* an `ast::Document` and an
`ExecutableDocument`. In a later PR we’ll want to run Rust validation
early and have the rest of a request lifecycle only deal with
`ExecutableDocument`, but as long as we rely on TypeScript validation
some things still need to work at the AST level.

~~This PR starts as a draft because of remaining failing tests:~~

* `cargo test --lib`
- [x]
plugins::telemetry::metrics::apollo::test::apollo_metrics_validation_failure
  - [x] router::tests::schema_update_test
  - [x] spec::query::tests::reformat_response_data_best_effort
* `cargo test --test integration_tests`
  - [x] api_schema_hides_field
  - [x] defer_path_with_disabled_config
  - [x] validation_errors_from_rust

<!-- start metadata -->
---

**Checklist**

Complete the checklist (and note appropriate exceptions) before the PR
is marked ready-for-review.

- [x] Changes are compatible[^1]
- [ ] Documentation[^2] completed
- [x] Performance impact assessed and acceptable
- Tests added and passing[^3]
    - [ ] Unit Tests
    - [ ] Integration Tests
    - [ ] Manual Tests

**Exceptions**

*Note any exceptions here*

**Notes**

[^1]: It may be appropriate to bring upcoming changes to the attention
of other (impacted) groups. Please endeavour to do this before seeking
PR approval. The mechanism for doing this will vary considerably, so use
your judgement as to how and when to do this.
[^2]: Configuration is an important part of many changes. Where
applicable please try to document configuration examples.
[^3]: Tick whichever testing boxes are applicable. If you are adding
Manual Tests, please document the manual testing (extensively) in the
Exceptions.
  • Loading branch information
SimonSapin authored Oct 20, 2023
1 parent 72e100d commit cd5e0e2
Show file tree
Hide file tree
Showing 89 changed files with 1,625 additions and 2,180 deletions.
50 changes: 33 additions & 17 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -200,34 +200,35 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"

[[package]]
name = "apollo-compiler"
version = "0.10.0"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4593ed026f92c0e79bc11a050f060af72a4fadaccdfefd211263d85f9be8048b"
checksum = "bb2436eb22464134efc641e508b33229361b27a3d5b6f03242b66b170ab8786c"
dependencies = [
"apollo-parser 0.5.3",
"apollo-parser 0.6.3",
"ariadne",
"indexmap 1.9.3",
"ordered-float 3.9.0",
"indexmap 2.0.2",
"ordered-float 4.1.0",
"rowan",
"salsa",
"serde",
"thiserror",
"uuid",
]

[[package]]
name = "apollo-compiler"
version = "0.11.3"
version = "1.0.0-beta.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb2436eb22464134efc641e508b33229361b27a3d5b6f03242b66b170ab8786c"
checksum = "a5ff474a85ea7b22c944aba74bab8863366adde503d00864d01da2284c670aa8"
dependencies = [
"apollo-parser 0.6.3",
"apollo-parser 0.7.1",
"ariadne",
"indexmap 2.0.2",
"ordered-float 4.1.0",
"rowan",
"salsa",
"serde",
"thiserror",
"triomphe",
"uuid",
]

Expand All @@ -244,19 +245,20 @@ dependencies = [

[[package]]
name = "apollo-parser"
version = "0.5.3"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec05c087cc9d21576b18337d9dbaadc87cea1b33c4f2b8d59e735ed90e880984"
checksum = "4b3cd0ce63c32c83e035757af12e3ae30566ce5d1ae183c02a2dd089a0df65aa"
dependencies = [
"memchr",
"rowan",
"thiserror",
]

[[package]]
name = "apollo-parser"
version = "0.6.3"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b3cd0ce63c32c83e035757af12e3ae30566ce5d1ae183c02a2dd089a0df65aa"
checksum = "c382f531987366a6954ac687305652b1428b049ca1294b4502b0a9dbbf0d37b8"
dependencies = [
"memchr",
"rowan",
Expand All @@ -269,9 +271,7 @@ version = "1.33.0"
dependencies = [
"access-json",
"anyhow",
"apollo-compiler 0.11.3",
"apollo-encoder",
"apollo-parser 0.6.3",
"apollo-compiler 1.0.0-beta.4",
"arc-swap",
"askama",
"async-compression",
Expand Down Expand Up @@ -6197,6 +6197,12 @@ dependencies = [
"der",
]

[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"

[[package]]
name = "static_assertions"
version = "1.1.0"
Expand Down Expand Up @@ -6282,7 +6288,7 @@ name = "supergraph_sdl"
version = "0.1.0"
dependencies = [
"anyhow",
"apollo-compiler 0.10.0",
"apollo-compiler 1.0.0-beta.4",
"apollo-router",
"async-trait",
"tower",
Expand Down Expand Up @@ -7018,6 +7024,16 @@ dependencies = [
"syn 1.0.109",
]

[[package]]
name = "triomphe"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee8098afad3fb0c54a9007aab6804558410503ad676d4633f9c2559a00ac0f"
dependencies = [
"serde",
"stable_deref_trait",
]

[[package]]
name = "try-lock"
version = "0.2.4"
Expand Down
12 changes: 6 additions & 6 deletions apollo-router/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,7 @@ features = ["docs_rs"]
askama = "0.12.1"
access-json = "0.1.0"
anyhow = "1.0.75"
apollo-compiler = "0.11.3"
apollo-encoder = "0.7.0"
apollo-parser = "0.6.3"
apollo-compiler = "=1.0.0-beta.4"
arc-swap = "1.6.0"
async-compression = { version = "0.4.4", features = [
"tokio",
Expand Down Expand Up @@ -136,7 +134,7 @@ once_cell = "1.18.0"
opentelemetry = { version = "0.20.0", features = [
"rt-tokio",
"metrics",
"testing"
"testing",
] }
opentelemetry_api = "0.20.0"
opentelemetry-aws = "0.8.0"
Expand Down Expand Up @@ -206,7 +204,7 @@ tonic = { version = "0.9.2", features = [
"transport",
"tls",
"tls-roots",
"gzip"
"gzip",
] }
tower = { version = "0.4.13", features = ["full"] }
tower-http = { version = "0.4.4", features = [
Expand All @@ -233,7 +231,9 @@ uuid = { version = "1.4.1", features = ["serde", "v4"] }
yaml-rust = "0.4.5"
wiremock = "0.5.19"
wsl = "0.1.0"
tokio-tungstenite = { version = "0.20.1", features = ["rustls-tls-native-roots"] }
tokio-tungstenite = { version = "0.20.1", features = [
"rustls-tls-native-roots",
] }
tokio-rustls = "0.24.1"
http-serde = "1.1.3"
hmac = "0.12.1"
Expand Down
28 changes: 16 additions & 12 deletions apollo-router/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Router errors.
use std::sync::Arc;

use apollo_compiler::ApolloDiagnostic;
use displaydoc::Display;
use lazy_static::__Deref;
use router_bridge::introspect::IntrospectionError;
Expand Down Expand Up @@ -475,7 +474,7 @@ impl From<SpecError> for QueryPlannerError {
impl From<ValidationErrors> for QueryPlannerError {
fn from(err: ValidationErrors) -> Self {
QueryPlannerError::OperationValidationErrors(
err.errors.iter().map(ApolloDiagnostic::to_json).collect(),
err.errors.iter().map(|e| e.to_json()).collect(),
)
}
}
Expand Down Expand Up @@ -554,9 +553,9 @@ pub(crate) enum SchemaError {
}

/// Collection of schema validation errors.
#[derive(Clone, Debug)]
#[derive(Debug)]
pub(crate) struct ParseErrors {
pub(crate) errors: Vec<apollo_parser::Error>,
pub(crate) errors: apollo_compiler::Diagnostics,
}

impl std::fmt::Display for ParseErrors {
Expand All @@ -566,8 +565,7 @@ impl std::fmt::Display for ParseErrors {
if i > 0 {
f.write_str("\n")?;
}
// TODO(@goto-bus-stop): display line/column once that is exposed from apollo-rs
write!(f, "at index {}: {}", error.index(), error.message())?;
write!(f, "{}", error)?;
}
let remaining = errors.count();
if remaining > 0 {
Expand All @@ -578,19 +576,19 @@ impl std::fmt::Display for ParseErrors {
}

/// Collection of schema validation errors.
#[derive(Clone, Debug)]
#[derive(Debug)]
pub(crate) struct ValidationErrors {
pub(crate) errors: Vec<apollo_compiler::ApolloDiagnostic>,
pub(crate) errors: apollo_compiler::Diagnostics,
}

impl IntoGraphQLErrors for ValidationErrors {
fn into_graphql_errors(self) -> Result<Vec<Error>, Self> {
Ok(self
.errors
.into_iter()
.iter()
.map(|diagnostic| {
Error::builder()
.message(diagnostic.data.to_string())
.message(diagnostic.message().to_string())
.locations(
diagnostic
.get_line_column()
Expand All @@ -616,9 +614,15 @@ impl std::fmt::Display for ValidationErrors {
f.write_str("\n")?;
}
if let Some(location) = error.get_line_column() {
write!(f, "[{}:{}] {}", location.line, location.column, error.data)?;
write!(
f,
"[{}:{}] {}",
location.line,
location.column,
error.message()
)?;
} else {
write!(f, "{}", error.data)?;
write!(f, "{}", error.message())?;
}
}
Ok(())
Expand Down
Loading

0 comments on commit cd5e0e2

Please sign in to comment.