Skip to content
This repository has been archived by the owner on May 3, 2024. It is now read-only.

Commit

Permalink
Implement the per-subgraph logic of query graph creation
Browse files Browse the repository at this point in the history
  • Loading branch information
sachindshinde committed Nov 8, 2023
1 parent 18a0e15 commit a551912
Show file tree
Hide file tree
Showing 9 changed files with 1,439 additions and 30 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ indexmap = "2.0.2"
thiserror = "1.0"
url = "2"
lazy_static = "1.4.0"
petgraph = "0.6.4"
strum = "0.25.0"
strum_macros = "0.25.2"

Expand Down
1 change: 0 additions & 1 deletion src/link/argument.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ pub(crate) fn directive_optional_fieldset_argument(
}
}

#[allow(dead_code)]
pub(crate) fn directive_required_fieldset_argument(
application: &Node<Directive>,
name: &str,
Expand Down
110 changes: 109 additions & 1 deletion src/link/federation_spec_definition.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
use crate::error::{FederationError, SingleFederationError};
use crate::link::argument::{
directive_optional_boolean_argument, directive_required_fieldset_argument,
};
use crate::link::spec::{Identity, Url, Version};
use crate::link::spec_definition::{SpecDefinition, SpecDefinitions};
use crate::schema::FederationSchema;
use apollo_compiler::ast::Argument;
use apollo_compiler::schema::{Directive, DirectiveDefinition, Value};
use apollo_compiler::schema::{
Directive, DirectiveDefinition, ExtendedType, NamedType, UnionType, Value,
};
use apollo_compiler::{Node, NodeStr};
use lazy_static::lazy_static;

pub(crate) const FEDERATION_ENTITY_TYPE_NAME_IN_SPEC: &str = "_Entity";
pub(crate) const FEDERATION_KEY_DIRECTIVE_NAME_IN_SPEC: &str = "key";
pub(crate) const FEDERATION_INTERFACEOBJECT_DIRECTIVE_NAME_IN_SPEC: &str = "interfaceObject";
pub(crate) const FEDERATION_EXTERNAL_DIRECTIVE_NAME_IN_SPEC: &str = "external";
Expand All @@ -20,6 +26,11 @@ pub(crate) const FEDERATION_RESOLVABLE_ARGUMENT_NAME: &str = "resolvable";
pub(crate) const FEDERATION_REASON_ARGUMENT_NAME: &str = "reason";
pub(crate) const FEDERATION_FROM_ARGUMENT_NAME: &str = "from";

pub(crate) struct KeyDirectiveArguments {
pub(crate) fields: NodeStr,
pub(crate) resolvable: bool,
}

pub(crate) struct FederationSpecDefinition {
url: Url,
}
Expand All @@ -34,6 +45,34 @@ impl FederationSpecDefinition {
}
}

pub(crate) fn entity_type_definition<'schema>(
&self,
schema: &'schema FederationSchema,
) -> Result<Option<(NamedType, &'schema Node<UnionType>)>, FederationError> {
// Note that the _Entity type is special in that:
// 1. Spec renaming doesn't take place for it (there's no prefixing or importing needed),
// in order to maintain backwards compatibility with Fed 1.
// 2. Its presence is optional; if absent, it means the subgraph has no resolvable keys.
match schema
.schema()
.types
.get(FEDERATION_ENTITY_TYPE_NAME_IN_SPEC)
{
Some(ExtendedType::Union(type_)) => Ok(Some((
NamedType::from(FEDERATION_ENTITY_TYPE_NAME_IN_SPEC),
type_,
))),
None => Ok(None),
_ => Err(SingleFederationError::Internal {
message: format!(
"Unexpectedly found non-union for federation spec's \"{}\" type definition",
FEDERATION_ENTITY_TYPE_NAME_IN_SPEC
),
}
.into()),
}
}

pub(crate) fn key_directive_definition<'schema>(
&self,
schema: &'schema FederationSchema,
Expand Down Expand Up @@ -76,6 +115,43 @@ impl FederationSpecDefinition {
})
}

pub(crate) fn key_directive_arguments(
&self,
application: &Node<Directive>,
) -> Result<KeyDirectiveArguments, FederationError> {
Ok(KeyDirectiveArguments {
fields: directive_required_fieldset_argument(
application,
FEDERATION_FIELDS_ARGUMENT_NAME,
)?,
resolvable: directive_optional_boolean_argument(
application,
FEDERATION_RESOLVABLE_ARGUMENT_NAME,
)?
.unwrap_or(false),
})
}

pub(crate) fn interface_object_directive_definition<'schema>(
&self,
schema: &'schema FederationSchema,
) -> Result<Option<&'schema Node<DirectiveDefinition>>, FederationError> {
if *self.version() < (Version { major: 2, minor: 3 }) {
return Ok(None);
}
self.directive_definition(schema, FEDERATION_INTERFACEOBJECT_DIRECTIVE_NAME_IN_SPEC)?
.ok_or_else(|| {
SingleFederationError::Internal {
message: format!(
"Unexpectedly could not find federation spec's \"@{}\" directive definition",
FEDERATION_INTERFACEOBJECT_DIRECTIVE_NAME_IN_SPEC
),
}
.into()
})
.map(Some)
}

pub(crate) fn interface_object_directive(
&self,
schema: &FederationSchema,
Expand All @@ -97,6 +173,22 @@ impl FederationSpecDefinition {
})
}

pub(crate) fn external_directive_definition<'schema>(
&self,
schema: &'schema FederationSchema,
) -> Result<&'schema Node<DirectiveDefinition>, FederationError> {
self.directive_definition(schema, FEDERATION_EXTERNAL_DIRECTIVE_NAME_IN_SPEC)?
.ok_or_else(|| {
SingleFederationError::Internal {
message: format!(
"Unexpectedly could not find federation spec's \"@{}\" directive definition",
FEDERATION_EXTERNAL_DIRECTIVE_NAME_IN_SPEC
),
}
.into()
})
}

pub(crate) fn external_directive(
&self,
schema: &FederationSchema,
Expand All @@ -120,6 +212,22 @@ impl FederationSpecDefinition {
})
}

pub(crate) fn requires_directive_definition<'schema>(
&self,
schema: &'schema FederationSchema,
) -> Result<&'schema Node<DirectiveDefinition>, FederationError> {
self.directive_definition(schema, FEDERATION_REQUIRES_DIRECTIVE_NAME_IN_SPEC)?
.ok_or_else(|| {
SingleFederationError::Internal {
message: format!(
"Unexpectedly could not find federation spec's \"@{}\" directive definition",
FEDERATION_REQUIRES_DIRECTIVE_NAME_IN_SPEC
),
}
.into()
})
}

pub(crate) fn requires_directive(
&self,
schema: &FederationSchema,
Expand Down
8 changes: 4 additions & 4 deletions src/link/join_spec_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::link::argument::{
use crate::link::spec::{Identity, Url, Version};
use crate::link::spec_definition::{SpecDefinition, SpecDefinitions};
use crate::schema::FederationSchema;
use apollo_compiler::schema::{Directive, DirectiveDefinition, EnumType, ExtendedType};
use apollo_compiler::schema::{Directive, DirectiveDefinition, EnumType, ExtendedType, NamedType};
use apollo_compiler::{Node, NodeStr};
use lazy_static::lazy_static;

Expand Down Expand Up @@ -91,14 +91,14 @@ impl JoinSpecDefinition {
pub(crate) fn graph_enum_definition<'schema>(
&self,
schema: &'schema FederationSchema,
) -> Result<&'schema Node<EnumType>, FederationError> {
let type_ = self
) -> Result<(NamedType, &'schema Node<EnumType>), FederationError> {
let (type_name, type_) = self
.type_definition(schema, JOIN_GRAPH_ENUM_NAME_IN_SPEC)?
.ok_or_else(|| SingleFederationError::Internal {
message: "Unexpectedly could not find join spec in schema".to_owned(),
})?;
if let ExtendedType::Enum(ref type_) = type_ {
Ok(type_)
Ok((type_name, type_))
} else {
Err(SingleFederationError::Internal {
message: format!(
Expand Down
35 changes: 19 additions & 16 deletions src/link/spec_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::error::{FederationError, SingleFederationError};
use crate::link::spec::{Identity, Url, Version};
use crate::link::Link;
use crate::schema::FederationSchema;
use apollo_compiler::schema::{DirectiveDefinition, ExtendedType};
use apollo_compiler::schema::{DirectiveDefinition, ExtendedType, NamedType};
use apollo_compiler::{Node, NodeStr};
use std::collections::btree_map::Keys;
use std::collections::BTreeMap;
Expand Down Expand Up @@ -102,22 +102,25 @@ pub(crate) trait SpecDefinition {
&self,
schema: &'schema FederationSchema,
name_in_spec: &str,
) -> Result<Option<&'schema ExtendedType>, FederationError> {
) -> Result<Option<(NamedType, &'schema ExtendedType)>, FederationError> {
match self.type_name_in_schema(schema, name_in_spec)? {
Some(name) => schema
.schema()
.types
.get(&NodeStr::new(&name))
.ok_or_else(|| {
SingleFederationError::Internal {
message: format!(
"Unexpectedly could not find spec type \"{}\" in schema",
name
),
}
.into()
})
.map(Some),
Some(name) => {
let name = NamedType::from(&name);
schema
.schema()
.types
.get(&name)
.ok_or_else(|| {
SingleFederationError::Internal {
message: format!(
"Unexpectedly could not find spec type \"{}\" in schema",
name
),
}
.into()
})
.map(|type_| Some((name, type_)))
}
None => Ok(None),
}
}
Expand Down
Loading

0 comments on commit a551912

Please sign in to comment.