Skip to content

Commit

Permalink
Read schema & check subtypes (#202)
Browse files Browse the repository at this point in the history
  • Loading branch information
cecton committed Oct 8, 2021
1 parent 4e8f7b9 commit ae9c728
Show file tree
Hide file tree
Showing 15 changed files with 416 additions and 166 deletions.
38 changes: 36 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
default-members = ["crates/apollo-router"]
default-members = ["crates/apollo-router", "crates/apollo-router-core"]
members = ["crates/apollo-router", "crates/apollo-router-core", "xtask"]

[patch.crates-io]
Expand Down
1 change: 1 addition & 0 deletions crates/apollo-router-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ name = "basic_composition"
harness = false

[dependencies]
apollo-parser = { git = "ssh://git@github.com/apollographql/apollo-rs.git", rev = "c6418141de4505e317ca30c97ac9e26bab8df0f0" }
derivative = "2.2.0"
displaydoc = "0.2"
futures = "0.3.17"
Expand Down
8 changes: 8 additions & 0 deletions crates/apollo-router-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,11 @@ impl From<serde_json::Error> for QueryPlannerError {
QueryPlannerError::ParseError(Arc::new(err))
}
}

#[derive(Debug, Error)]
pub enum SchemaError {
#[error(transparent)]
IoError(#[from] std::io::Error),
#[error("Parsing error(s)")]
ParseErrors(Vec<apollo_parser::Error>),
}
49 changes: 30 additions & 19 deletions crates/apollo-router-core/src/federated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,20 @@ pub struct FederatedGraph {
#[derivative(Debug = "ignore")]
query_planner: Box<dyn QueryPlanner>,
service_registry: Arc<dyn ServiceRegistry>,
schema: Arc<Schema>,
}

impl FederatedGraph {
/// Create a `FederatedGraph` instance used to execute a GraphQL query.
pub fn new(
query_planner: Box<dyn QueryPlanner>,
service_registry: Arc<dyn ServiceRegistry>,
schema: Arc<Schema>,
) -> Self {
Self {
query_planner,
service_registry,
schema,
}
}
}
Expand Down Expand Up @@ -103,16 +106,17 @@ impl Fetcher for FederatedGraph {
}
}
};
let service_registry = self.service_registry.clone();
let service_registry = Arc::clone(&self.service_registry);
let schema = Arc::clone(&self.schema);
let request = Arc::new(request);

let mut early_errors = Vec::new();

for err in validate_services_against_plan(service_registry.clone(), &plan) {
for err in validate_services_against_plan(Arc::clone(&service_registry), &plan) {
early_errors.push(err.to_graphql_error(None));
}

for err in validate_request_variables_against_plan(request.clone(), &plan) {
for err in validate_request_variables_against_plan(Arc::clone(&request), &plan) {
early_errors.push(err.to_graphql_error(None));
}

Expand All @@ -129,11 +133,12 @@ impl Fetcher for FederatedGraph {
let root = Path::empty();

execute(
response.clone(),
Arc::clone(&response),
&root,
&plan,
request,
service_registry.clone(),
Arc::clone(&service_registry),
Arc::clone(&schema),
)
.await;

Expand All @@ -155,6 +160,7 @@ fn execute<'a>(
plan: &'a PlanNode,
request: Arc<Request>,
service_registry: Arc<dyn ServiceRegistry>,
schema: Arc<Schema>,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> {
let span = tracing::info_span!("execution");
let _guard = span.enter();
Expand All @@ -166,11 +172,12 @@ fn execute<'a>(
PlanNode::Sequence { nodes } => {
for node in nodes {
execute(
response.clone(),
Arc::clone(&response),
current_dir,
node,
request.clone(),
service_registry.clone(),
Arc::clone(&request),
Arc::clone(&service_registry),
Arc::clone(&schema),
)
.instrument(tracing::trace_span!("execute-sequence"))
.await;
Expand All @@ -179,23 +186,25 @@ fn execute<'a>(
PlanNode::Parallel { nodes } => {
future::join_all(nodes.iter().map(|plan| {
execute(
response.clone(),
Arc::clone(&response),
current_dir,
plan,
request.clone(),
service_registry.clone(),
Arc::clone(&request),
Arc::clone(&service_registry),
Arc::clone(&schema),
)
}))
.instrument(tracing::trace_span!("execute-parallel"))
.await;
}
PlanNode::Fetch(info) => {
match fetch_node(
response.clone(),
Arc::clone(&response),
current_dir,
info,
request.clone(),
service_registry.clone(),
Arc::clone(&request),
Arc::clone(&service_registry),
Arc::clone(&schema),
)
.instrument(tracing::trace_span!("execute-fetch"))
.await
Expand All @@ -221,12 +230,13 @@ fn execute<'a>(
// this is the only command that actually changes the "current dir"
let current_dir = current_dir.join(path);
execute(
response.clone(),
Arc::clone(&response),
// a path can go over multiple json node!
&current_dir,
node,
request.clone(),
service_registry.clone(),
Arc::clone(&request),
Arc::clone(&service_registry),
Arc::clone(&schema),
)
.instrument(tracing::trace_span!("execute-flatten"))
.await;
Expand All @@ -246,6 +256,7 @@ async fn fetch_node<'a>(
}: &'a FetchNode,
request: Arc<Request>,
service_registry: Arc<dyn ServiceRegistry>,
schema: Arc<Schema>,
) -> Result<(), FetchError> {
if let Some(requires) = requires {
// We already checked that the service exists during planning
Expand All @@ -267,7 +278,7 @@ async fn fetch_node<'a>(
requires,
serde_json::to_string(&response.data).unwrap(),
);
let representations = response.select(current_dir, requires)?;
let representations = response.select(current_dir, requires, &schema)?;
variables.insert("representations".into(), representations);
}

Expand Down Expand Up @@ -345,7 +356,7 @@ async fn fetch_node<'a>(
.stream(
Request::builder()
.query(operation.clone())
.variables(variables.clone())
.variables(Arc::clone(&variables))
.build(),
)
.into_future()
Expand Down
2 changes: 2 additions & 0 deletions crates/apollo-router-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod json_ext;
mod query_planner;
mod request;
mod response;
mod schema;
mod traits;

pub use error::*;
Expand All @@ -12,6 +13,7 @@ pub use json_ext::*;
pub use query_planner::*;
pub use request::*;
pub use response::*;
pub use schema::*;
pub use traits::*;

pub mod prelude {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ pub struct HarmonizerQueryPlanner {

impl HarmonizerQueryPlanner {
/// Create a new harmonizer query planner
pub fn new(schema: String) -> Self {
Self { schema }
pub fn new(schema: &Schema) -> Self {
Self {
schema: schema.as_str().to_owned(),
}
}
}

Expand Down Expand Up @@ -49,7 +51,8 @@ mod tests {

#[test]
fn test_plan() {
let planner = HarmonizerQueryPlanner::new(include_str!("testdata/schema.graphql").into());
let planner =
HarmonizerQueryPlanner::new(&include_str!("testdata/schema.graphql").parse().unwrap());
let result = planner.get(
include_str!("testdata/query.graphql").into(),
None,
Expand All @@ -70,7 +73,7 @@ mod tests {

#[test]
fn test_plan_error() {
let planner = HarmonizerQueryPlanner::new("".to_string());
let planner = HarmonizerQueryPlanner::new(&"".parse().unwrap());
let result = planner.get("".into(), None, QueryPlanOptions::default());
assert_eq!(
"Query planning had errors: Planning errors: UNKNOWN: Syntax Error: Unexpected <EOF>.",
Expand Down
Loading

0 comments on commit ae9c728

Please sign in to comment.