Skip to content

Commit

Permalink
Fix returning thrown errors from QP (#457)
Browse files Browse the repository at this point in the history
The Rust side is expecting a single string in `exception.stacktrace`,
but JS was providing an array of strings. It doesn't really make sense
to split `error.toString()` as normally the first line will be the error
message, and only the later lines will be part of the stack trace, so
I think it's best if we use a single string.

Ref:

https://github.com/apollographql/federation-rs/blob/35052d8064e7ca50d09226febdbbe0d55cc5d18b/federation-2/router-bridge/src/planner.rs#L121-L136

Fixes apollographql/router#4783
  • Loading branch information
goto-bus-stop authored Mar 26, 2024
1 parent 47e99a2 commit b0fa276
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 2 deletions.
4 changes: 2 additions & 2 deletions federation-2/router-bridge/js-src/plan_worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ async function run() {
extensions: {
code: "QUERY_PLANNING_FAILED",
exception: {
stacktrace: e.toString().split(/\n/),
stacktrace: e.toString(),
},
},
};
Expand All @@ -330,7 +330,7 @@ async function run() {
extensions: {
code: "QUERY_PLANNING_FAILED",
exception: {
stacktrace: e.toString().split(/\n/),
stacktrace: e.toString(),
},
},
};
Expand Down
85 changes: 85 additions & 0 deletions federation-2/router-bridge/src/planner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2216,4 +2216,89 @@ feature https://specs.apollo.dev/unsupported-feature/v0.1 is for: SECURITY but i
.data
.unwrap()).unwrap());
}

#[tokio::test]
async fn propagate_internal_qp_errors() {
let schema = r#"
schema
@link(url: "https://specs.apollo.dev/link/v1.0")
@link(url: "https://specs.apollo.dev/join/v0.2", for: EXECUTION)
{
query: Query
subscription: Subscription
}
directive @join__field(graph: join__Graph!, requires: join__FieldSet, provides: join__FieldSet, type: String, external: Boolean, override: String, usedOverridden: Boolean) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION
directive @join__graph(name: String!, url: String!) on ENUM_VALUE
directive @join__implements(graph: join__Graph!, interface: String!) repeatable on OBJECT | INTERFACE
directive @join__type(graph: join__Graph!, key: join__FieldSet, extension: Boolean! = false, resolvable: Boolean! = true) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR
directive @link(url: String, as: String, for: link__Purpose, import: [link__Import]) repeatable on SCHEMA
scalar link__Import
enum link__Purpose {
SECURITY
EXECUTION
}
type Computer
@join__type(graph: COMPUTERS)
{
id: ID!
errorField: String
nonNullErrorField: String!
gpus: [GPU]
}
type GPU @join__type(graph: COMPUTERS) @join__type(graph: GPUS) {
id: ID!
wattage: Int! @join__field(graph: GPUS)
}
scalar join__FieldSet
enum join__Graph {
COMPUTERS @join__graph(name: "computers", url: "http://localhost:4001/")
GPUS @join__graph(name: "gpus", url: "http://localhost:4002/")
}
type Query
@join__type(graph: COMPUTERS)
{
computer(id: ID!): Computer
}
type Subscription @join__type(graph: COMPUTERS) {
computer(id: ID!): Computer
}"#;

let planner = Planner::<serde_json::Value>::new(
schema.to_string(),
QueryPlannerConfig {
incremental_delivery: Some(IncrementalDeliverySupport {
enable_defer: Some(true),
}),
graphql_validation: true,
reuse_query_fragments: None,
generate_query_fragments: None,
debug: Default::default(),
},
)
.await
.unwrap();

insta::assert_snapshot!(serde_json::to_string_pretty(
&planner
.plan(
"subscription { computer(id: 1) { ... @defer { gpus { wattage } } } }"
.to_string(),
None,
PlanOptions::default(),
)
.await
.unwrap()
.errors
.unwrap()
)
.unwrap());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
source: router-bridge/src/planner.rs
expression: "serde_json::to_string_pretty(&planner.plan(\"subscription { computer(id: 1) { ... @defer { gpus { wattage } } } }\".to_string(),\n None,\n PlanOptions::default()).await.unwrap().errors.unwrap()).unwrap()"
---
[
{
"message": "@defer is not supported on subscriptions",
"extensions": {
"code": "QUERY_PLANNING_FAILED",
"exception": {
"stacktrace": "Error: @defer is not supported on subscriptions"
}
}
}
]

0 comments on commit b0fa276

Please sign in to comment.