Skip to content

Commit

Permalink
Query Graph Traversal: Part 2 (apollographql/federation-next#161)
Browse files Browse the repository at this point in the history
  • Loading branch information
sachindshinde authored Feb 6, 2024
1 parent c8c7a51 commit e22f16a
Show file tree
Hide file tree
Showing 8 changed files with 1,542 additions and 78 deletions.
19 changes: 19 additions & 0 deletions apollo-federation/src/link/argument.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::error::{FederationError, SingleFederationError};
use crate::link::graphql_definition::BooleanOrVariable;
use apollo_compiler::ast::Value;
use apollo_compiler::schema::{Directive, Name};
use apollo_compiler::{Node, NodeStr};
Expand Down Expand Up @@ -141,3 +142,21 @@ pub(crate) fn directive_required_boolean_argument(
.into()
})
}

pub(crate) fn directive_optional_variable_boolean_argument(
application: &Node<Directive>,
name: &Name,
) -> Result<Option<BooleanOrVariable>, FederationError> {
match application.argument_by_name(name) {
Some(value) => match value.deref() {
Value::Variable(name) => Ok(Some(BooleanOrVariable::Variable(name.clone()))),
Value::Boolean(value) => Ok(Some(BooleanOrVariable::Boolean(*value))),
Value::Null => Ok(None),
_ => Err(FederationError::internal(format!(
"Argument \"{}\" of directive \"@{}\" must be a boolean.",
name, application.name
))),
},
None => Ok(None),
}
}
17 changes: 15 additions & 2 deletions apollo-federation/src/link/graphql_definition.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
use apollo_compiler::executable::Name;
use apollo_compiler::NodeStr;
use crate::error::FederationError;
use crate::link::argument::{
directive_optional_string_argument, directive_optional_variable_boolean_argument,
};
use apollo_compiler::executable::{Directive, Name};
use apollo_compiler::{name, Node, NodeStr};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(crate) struct DeferDirectiveArguments {
label: Option<NodeStr>,
if_: Option<BooleanOrVariable>,
}

pub(crate) fn defer_directive_arguments(
application: &Node<Directive>,
) -> Result<DeferDirectiveArguments, FederationError> {
Ok(DeferDirectiveArguments {
label: directive_optional_string_argument(application, &name!("label"))?,
if_: directive_optional_variable_boolean_argument(application, &name!("if"))?,
})
}

/// This struct is meant for recording the original structure/intent of `@skip`/`@include`
/// applications within the elements of a `GraphPath`. Accordingly, the order of them matters within
/// a `Vec`, and superfluous struct instances aren't elided; `Conditions` is the more appropriate
Expand Down
49 changes: 35 additions & 14 deletions apollo-federation/src/query_graph/condition_resolver.rs
Original file line number Diff line number Diff line change
@@ -1,41 +1,62 @@
use crate::error::FederationError;
use crate::query_graph::graph_path::{
ExcludedConditions, ExcludedDestinations, OpGraphPathContext,
};
use crate::query_graph::path_tree::OpPathTree;
use crate::query_plan::QueryPlanCost;
use petgraph::graph::EdgeIndex;
use std::sync::Arc;

/// Note that `ConditionResolver`s are guaranteed to be only called for edge with conditions.
pub(crate) trait ConditionResolver {
fn resolve(
&mut self,
edge: EdgeIndex,
context: OpGraphPathContext,
excluded_destinations: ExcludedDestinations,
excluded_conditions: ExcludedConditions,
) -> ConditionResolution;
context: &OpGraphPathContext,
excluded_destinations: &ExcludedDestinations,
excluded_conditions: &ExcludedConditions,
) -> Result<ConditionResolution, FederationError>;
}

pub(crate) struct ConditionResolution {
satisfied: bool,
cost: QueryPlanCost,
path_tree: Option<OpPathTree>,
// Note that this is not guaranteed to be set even if satistied === false.
unsatisfied_condition_reason: Option<UnsatisfiedConditionReason>,
#[derive(Debug, Clone)]
pub(crate) enum ConditionResolution {
Satisfied {
cost: QueryPlanCost,
path_tree: Option<Arc<OpPathTree>>,
},
Unsatisfied {
reason: Option<UnsatisfiedConditionReason>,
},
}

#[derive(Debug, Clone)]
pub(crate) enum UnsatisfiedConditionReason {
NoPostRequireKey,
}

impl ConditionResolution {
pub(crate) fn no_conditions() -> Self {
Self::Satisfied {
cost: 0,
path_tree: None,
}
}

pub(crate) fn unsatisfied_conditions() -> Self {
Self::Unsatisfied { reason: None }
}
}

pub(crate) struct CachingConditionResolver;

impl ConditionResolver for CachingConditionResolver {
fn resolve(
&mut self,
_edge: EdgeIndex,
_context: OpGraphPathContext,
_excluded_destinations: ExcludedDestinations,
_excluded_conditions: ExcludedConditions,
) -> ConditionResolution {
_context: &OpGraphPathContext,
_excluded_destinations: &ExcludedDestinations,
_excluded_conditions: &ExcludedConditions,
) -> Result<ConditionResolution, FederationError> {
todo!()
}
}
Loading

0 comments on commit e22f16a

Please sign in to comment.