Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/main/java/graphql/schema/DataFetcherFactories.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,17 @@ public class DataFetcherFactories {
* @return a data fetcher factory that always returns the provided data fetcher
*/
public static <T> DataFetcherFactory<T> useDataFetcher(DataFetcher<T> dataFetcher) {
return fieldDefinition -> dataFetcher;
return new DataFetcherFactory<T>() {
@Override
public DataFetcher<T> get(DataFetcherFactoryEnvironment environment) {
return dataFetcher;
}

@Override
public DataFetcher<T> getViaField(GraphQLFieldDefinition fieldDefinition) {
return dataFetcher;
}
};
}

/**
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/graphql/schema/DataFetcherFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,17 @@ public interface DataFetcherFactory<T> {
*/
DataFetcher<T> get(DataFetcherFactoryEnvironment environment);

/**
* Returns a {@link graphql.schema.DataFetcher} given the field definition
* which is cheaper in object allocation terms.
*
* @param fieldDefinition the field that needs the data fetcher
*
* @return a data fetcher
*/

default DataFetcher<T> getViaField(GraphQLFieldDefinition fieldDefinition) {
return null;
}
Copy link
Member Author

Choose a reason for hiding this comment

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

DataFetcherFactoryEnvironment is a "parameter" object that ONLYT wraps a GraphQLFieldDefinition

It was put in place for "future expansion reasons" but we never expanded it and never had to. So this one as a bad bet since we have to make a new object just to pass 1 object we already have

This method undoes that and says we can lookup via just the GraphQLFieldDefinition object


}
12 changes: 9 additions & 3 deletions src/main/java/graphql/schema/GraphQLCodeRegistry.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,15 @@ private static DataFetcher<?> getDataFetcherImpl(FieldCoordinates coordinates, G
dataFetcherFactory = defaultDataFetcherFactory;
}
}
return dataFetcherFactory.get(newDataFetchingFactoryEnvironment()
.fieldDefinition(fieldDefinition)
.build());
// call direct from the field - cheaper to not make a new environment object
DataFetcher<?> dataFetcher = dataFetcherFactory.getViaField(fieldDefinition);
if (dataFetcher == null) {
DataFetcherFactoryEnvironment factoryEnvironment = newDataFetchingFactoryEnvironment()
.fieldDefinition(fieldDefinition)
.build();
dataFetcher = dataFetcherFactory.get(factoryEnvironment);
}
return dataFetcher;
}

private static boolean hasDataFetcherImpl(FieldCoordinates coords, Map<FieldCoordinates, DataFetcherFactory<?>> dataFetcherMap, Map<String, DataFetcherFactory<?>> systemDataFetcherMap) {
Expand Down
26 changes: 16 additions & 10 deletions src/main/java/graphql/schema/idl/SchemaGeneratorHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -802,23 +802,27 @@ GraphQLFieldDefinition buildField(BuildContext buildCtx, TypeDefinition<?> paren
// if they have already wired in a fetcher - then leave it alone
FieldCoordinates coordinates = FieldCoordinates.coordinates(parentType.getName(), fieldDefinition.getName());
if (!buildCtx.getCodeRegistry().hasDataFetcher(coordinates)) {
DataFetcherFactory<?> dataFetcherFactory = buildDataFetcherFactory(buildCtx,
Optional<DataFetcherFactory<?>> dataFetcherFactory = buildDataFetcherFactory(buildCtx,
parentType,
fieldDef,
fieldType,
appliedDirectives.first,
appliedDirectives.second);
buildCtx.getCodeRegistry().dataFetcher(coordinates, dataFetcherFactory);

// if the dataFetcherFactory is empty, then it must have been the code registry default one
// and hence we don't need to make a "map entry" in the code registry since it will be defaulted
// anyway
dataFetcherFactory.ifPresent(fetcherFactory -> buildCtx.getCodeRegistry().dataFetcher(coordinates, fetcherFactory));
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the saving - we are not holding a DF per field when it would be defaulted in the code registry.

If we had 90% DFs that are the default - eg PropertyDataFetchers - then we save all those entries in memory

}
return directivesObserve(buildCtx, fieldDefinition);
}

private DataFetcherFactory<?> buildDataFetcherFactory(BuildContext buildCtx,
TypeDefinition<?> parentType,
FieldDefinition fieldDef,
GraphQLOutputType fieldType,
List<GraphQLDirective> directives,
List<GraphQLAppliedDirective> appliedDirectives) {
private Optional<DataFetcherFactory<?>> buildDataFetcherFactory(BuildContext buildCtx,
TypeDefinition<?> parentType,
FieldDefinition fieldDef,
GraphQLOutputType fieldType,
List<GraphQLDirective> directives,
List<GraphQLAppliedDirective> appliedDirectives) {
String fieldName = fieldDef.getName();
String parentTypeName = parentType.getName();
TypeDefinitionRegistry typeRegistry = buildCtx.getTypeRegistry();
Expand Down Expand Up @@ -848,7 +852,9 @@ private DataFetcherFactory<?> buildDataFetcherFactory(BuildContext buildCtx,
if (dataFetcher == null) {
DataFetcherFactory<?> codeRegistryDFF = codeRegistry.getDefaultDataFetcherFactory();
if (codeRegistryDFF != null) {
return codeRegistryDFF;
// this will use the default of the code registry when its
// asked for at runtime
return Optional.empty();
}
dataFetcher = dataFetcherOfLastResort();
}
Expand All @@ -857,7 +863,7 @@ private DataFetcherFactory<?> buildDataFetcherFactory(BuildContext buildCtx,
}
dataFetcherFactory = DataFetcherFactories.useDataFetcher(dataFetcher);
}
return dataFetcherFactory;
return Optional.of(dataFetcherFactory);
}

GraphQLArgument buildArgument(BuildContext buildCtx, InputValueDefinition valueDefinition) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import graphql.schema.DataFetcher
import graphql.schema.DataFetchingEnvironment
import graphql.schema.LightDataFetcher
import graphql.schema.PropertyDataFetcher
import graphql.schema.SingletonPropertyDataFetcher
import graphql.schema.StaticDataFetcher
import org.awaitility.Awaitility
import org.jetbrains.annotations.NotNull
Expand Down Expand Up @@ -100,7 +101,7 @@ class InstrumentationTest extends Specification {

instrumentation.dfClasses.size() == 2
instrumentation.dfClasses[0] == StaticDataFetcher.class
LightDataFetcher.class.isAssignableFrom(instrumentation.dfClasses[1])
instrumentation.dfClasses[1] == SingletonPropertyDataFetcher.class

instrumentation.dfInvocations.size() == 2

Expand Down
10 changes: 10 additions & 0 deletions src/test/groovy/graphql/schema/DataFetcherFactoriesTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,14 @@ class DataFetcherFactoriesTest extends Specification {
then:
value == "goodbye"
}

def "will use given df via field"() {
def fetcherFactory = DataFetcherFactories.useDataFetcher(pojoDF)

when:
def value = fetcherFactory.getViaField(null).get(null)

then:
value == "goodbye"
}
}