Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Defer support on ENFs #3395

Merged
merged 34 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
9856678
WIP: Implement support for defer in ExecutableNormalizedOperationFactory
felipe-gdr-atlassian Dec 5, 2023
37b1c4a
WIP: ENF to AST Compiler basic implementation
felipe-gdr-atlassian Dec 5, 2023
8b68720
Fix edge case with non-conditional fields in fragments
felipe-gdr-atlassian Dec 12, 2023
c85cbed
Fix comment and test
felipe-gdr-atlassian Dec 12, 2023
df767cb
Remove commented out code
felipe-gdr Dec 12, 2023
7c047e2
Fix assert error message
felipe-gdr Dec 12, 2023
80dc093
Add tests for 'if' argument
felipe-gdr Dec 12, 2023
407efba
Add dedicated entry point for defer support
felipe-gdr Dec 13, 2023
17f1fab
Add dedicated entrypoint with defer support in the ENFOperationFactory
felipe-gdr Dec 13, 2023
86f9dbe
Add Javadocs
felipe-gdr Dec 14, 2023
0f4abf4
Lots of small adjustments
felipe-gdr Dec 14, 2023
444f775
Add test case for multiple defers at the same level
felipe-gdr Dec 15, 2023
32881a3
Moving over to new implementation: changed method signatures
felipe-gdr Dec 18, 2023
8fe9e38
Conclude refactoring that moves defer support out of ENFs and into ENOs
felipe-gdr Dec 20, 2023
da2761e
Clean up defer execution code
felipe-gdr Dec 20, 2023
3f6e480
Add missing Javadoc
felipe-gdr Dec 20, 2023
7f0a37c
Add Javadocs and one more test
felipe-gdr-atlassian Dec 20, 2023
e979b77
Apply code formatting
felipe-gdr-atlassian Jan 2, 2024
202573f
Fix edge case
felipe-gdr-atlassian Jan 2, 2024
4db220e
Replace Guava's Multimap with Map in public APIs
felipe-gdr-atlassian Jan 2, 2024
6446ad4
Big refactoring:
felipe-gdr-atlassian Jan 5, 2024
b9b0f54
WIP: attempt of getting rid of the NormalizedDeferExecutionFactory
felipe-gdr-atlassian Jan 9, 2024
ca1f6d4
Revert "WIP: attempt of getting rid of the NormalizedDeferExecutionFa…
felipe-gdr-atlassian Jan 9, 2024
6ba3e09
Remove excessive normalization that was resulting in reduced number o…
felipe-gdr-atlassian Jan 9, 2024
b71a9a4
Big refactor: capture defer executions directly in ENFs
felipe-gdr-atlassian Jan 9, 2024
6a0f9f7
Merge branch 'master' into defer-support-in-enf
felipe-gdr-atlassian Jan 9, 2024
eda84d3
post merge adjustments
felipe-gdr-atlassian Jan 9, 2024
87a5b52
Remove irrelevant parameter
felipe-gdr-atlassian Jan 9, 2024
5943b7c
Minor refactors
felipe-gdr-atlassian Jan 9, 2024
b04eadc
Rename predicate function
felipe-gdr-atlassian Jan 9, 2024
f500132
Rename test and add better documentation
felipe-gdr-atlassian Jan 9, 2024
f3e5c84
Small changes after Andi's review
felipe-gdr-atlassian Jan 10, 2024
a91fa64
Add Javadoc for DeferExecution
felipe-gdr-atlassian Jan 10, 2024
b22fe7a
minor changes
andimarek Jan 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 24 additions & 1 deletion src/main/java/graphql/Directives.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package graphql;


import graphql.language.BooleanValue;
import graphql.language.Description;
import graphql.language.DirectiveDefinition;
import graphql.language.StringValue;
Expand Down Expand Up @@ -33,14 +34,14 @@ public class Directives {
private static final String SPECIFIED_BY = "specifiedBy";
private static final String DEPRECATED = "deprecated";
private static final String ONE_OF = "oneOf";
private static final String DEFER = "defer";

public static final String NO_LONGER_SUPPORTED = "No longer supported";
public static final DirectiveDefinition DEPRECATED_DIRECTIVE_DEFINITION;
public static final DirectiveDefinition SPECIFIED_BY_DIRECTIVE_DEFINITION;
@ExperimentalApi
public static final DirectiveDefinition ONE_OF_DIRECTIVE_DEFINITION;


static {
DEPRECATED_DIRECTIVE_DEFINITION = DirectiveDefinition.newDirectiveDefinition()
.name(DEPRECATED)
Expand Down Expand Up @@ -77,6 +78,28 @@ public class Directives {
.build();
}

/**
* The @defer directive can be used to defer sending data for a fragment until later in the query.
* This is an opt-in directive that is not available unless it is explicitly put into the schema.
*/
@ExperimentalApi
public static final GraphQLDirective DeferDirective = GraphQLDirective.newDirective()
.name("defer")
.description("This directive allows results to be deferred during execution")
.validLocations(FRAGMENT_SPREAD, INLINE_FRAGMENT)
.argument(newArgument()
.name("if")
.type(nonNull(GraphQLBoolean))
.description("Deferred behaviour is controlled by this argument")
.defaultValueLiteral(BooleanValue.newBooleanValue(true).build())
)
.argument(newArgument()
.name("label")
.type(GraphQLString)
.description("A unique label that represents the fragment being deferred")
)
.build();

public static final GraphQLDirective IncludeDirective = GraphQLDirective.newDirective()
.name("include")
.description("Directs the executor to include this field or fragment only when the `if` argument is true")
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/graphql/ExperimentalApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@

/**
* This represents code that the graphql-java project considers experimental API and while our intention is that it will
* progress to be {@link PublicApi}, its existence, signature of behavior may change between releases.
*
* In general unnecessary changes will be avoided but you should not depend on experimental classes being stable
* progress to be {@link PublicApi}, its existence, signature or behavior may change between releases.
* <p>
* In general unnecessary changes will be avoided, but you should not depend on experimental classes being stable.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {CONSTRUCTOR, METHOD, TYPE, FIELD})
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/graphql/execution/FieldCollector.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

/**
* A field collector can iterate over field selection sets and build out the sub fields that have been selected,
* expanding named and inline fragments as it goes.s
* expanding named and inline fragments as it goes.
*/
@Internal
public class FieldCollector {
Expand Down
10 changes: 0 additions & 10 deletions src/main/java/graphql/normalized/ExecutableNormalizedField.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ public class ExecutableNormalizedField {
private final String fieldName;
private final int level;


private ExecutableNormalizedField(Builder builder) {
this.alias = builder.alias;
this.resolvedArguments = builder.resolvedArguments;
Expand Down Expand Up @@ -261,7 +260,6 @@ public void clearChildren() {
* WARNING: This is not always the key in the execution result, because of possible field aliases.
*
* @return the name of this {@link ExecutableNormalizedField}
*
* @see #getResultKey()
* @see #getAlias()
*/
Expand All @@ -271,7 +269,6 @@ public String getName() {

/**
* @return the same value as {@link #getName()}
*
* @see #getResultKey()
* @see #getAlias()
*/
Expand All @@ -284,7 +281,6 @@ public String getFieldName() {
* This is either a field alias or the value of {@link #getName()}
*
* @return the result key for this {@link ExecutableNormalizedField}.
*
* @see #getName()
*/
public String getResultKey() {
Expand All @@ -296,7 +292,6 @@ public String getResultKey() {

/**
* @return the field alias used or null if there is none
*
* @see #getResultKey()
* @see #getName()
*/
Expand All @@ -315,7 +310,6 @@ public ImmutableList<Argument> getAstArguments() {
* Returns an argument value as a {@link NormalizedInputValue} which contains its type name and its current value
*
* @param name the name of the argument
*
* @return an argument value
*/
public NormalizedInputValue getNormalizedArgument(String name) {
Expand Down Expand Up @@ -364,7 +358,6 @@ public String getSingleObjectTypeName() {
return objectTypeNames.iterator().next();
}


/**
* @return a helper method show field details
*/
Expand Down Expand Up @@ -414,7 +407,6 @@ public List<ExecutableNormalizedField> getChildren() {
* Returns the list of child fields that would have the same result key
*
* @param resultKey the result key to check
*
* @return a list of all direct {@link ExecutableNormalizedField} children with the specified result key
*/
public List<ExecutableNormalizedField> getChildrenWithSameResultKey(String resultKey) {
Expand All @@ -435,7 +427,6 @@ public List<ExecutableNormalizedField> getChildren(int includingRelativeLevel) {
* This returns the child fields that can be used if the object is of the specified object type
*
* @param objectTypeName the object type
*
* @return a list of child fields that would apply to that object type
*/
public List<ExecutableNormalizedField> getChildren(String objectTypeName) {
Expand Down Expand Up @@ -568,7 +559,6 @@ public static Builder newNormalizedField() {
* Allows this {@link ExecutableNormalizedField} to be transformed via a {@link Builder} consumer callback
*
* @param builderConsumer the consumer given a builder
*
* @return a new transformed {@link ExecutableNormalizedField}
*/
public ExecutableNormalizedField transform(Consumer<Builder> builderConsumer) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import com.google.common.collect.ImmutableListMultimap;
import graphql.Assert;
import graphql.ExperimentalApi;
import graphql.PublicApi;
import graphql.execution.MergedField;
import graphql.execution.ResultPath;
import graphql.execution.directives.QueryDirectives;
import graphql.language.Field;
import graphql.language.OperationDefinition;
import graphql.normalized.incremental.DeferExecution;
import graphql.schema.FieldCoordinates;
import graphql.schema.GraphQLFieldsContainer;

Expand All @@ -30,6 +32,7 @@ public class ExecutableNormalizedOperation {
private final ImmutableListMultimap<Field, ExecutableNormalizedField> fieldToNormalizedField;
private final Map<ExecutableNormalizedField, MergedField> normalizedFieldToMergedField;
private final Map<ExecutableNormalizedField, QueryDirectives> normalizedFieldToQueryDirectives;
private final ImmutableListMultimap<ExecutableNormalizedField, DeferExecution> normalizedFieldToDeferExecution;
private final ImmutableListMultimap<FieldCoordinates, ExecutableNormalizedField> coordinatesToNormalizedFields;

public ExecutableNormalizedOperation(
Expand All @@ -39,7 +42,8 @@ public ExecutableNormalizedOperation(
ImmutableListMultimap<Field, ExecutableNormalizedField> fieldToNormalizedField,
Map<ExecutableNormalizedField, MergedField> normalizedFieldToMergedField,
Map<ExecutableNormalizedField, QueryDirectives> normalizedFieldToQueryDirectives,
ImmutableListMultimap<FieldCoordinates, ExecutableNormalizedField> coordinatesToNormalizedFields
ImmutableListMultimap<FieldCoordinates, ExecutableNormalizedField> coordinatesToNormalizedFields,
ImmutableListMultimap<ExecutableNormalizedField, DeferExecution> normalizedFieldToDeferExecution
) {
this.operation = operation;
this.operationName = operationName;
Expand All @@ -48,6 +52,7 @@ public ExecutableNormalizedOperation(
this.normalizedFieldToMergedField = normalizedFieldToMergedField;
this.normalizedFieldToQueryDirectives = normalizedFieldToQueryDirectives;
this.coordinatesToNormalizedFields = coordinatesToNormalizedFields;
this.normalizedFieldToDeferExecution = normalizedFieldToDeferExecution;
}

/**
Expand Down Expand Up @@ -126,6 +131,15 @@ public Map<ExecutableNormalizedField, QueryDirectives> getNormalizedFieldToQuery

}

/**
* @return a map of {@link ExecutableNormalizedField} to its {@link DeferExecution}
*/
@ExperimentalApi
public ImmutableListMultimap<ExecutableNormalizedField, DeferExecution> getNormalizedFieldToDeferExecution() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this a Map

return normalizedFieldToDeferExecution;
}


/**
* This looks up the {@link QueryDirectives} associated with the given {@link ExecutableNormalizedField}
*
Expand Down