Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
9 changes: 6 additions & 3 deletions src/main/java/graphql/GraphqlErrorHelper.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package graphql;

import graphql.language.SourceLocation;
import graphql.util.FpKit;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static graphql.collect.ImmutableKit.mapAndDropNulls;

Expand Down Expand Up @@ -77,8 +77,11 @@ public static Object location(SourceLocation location) {
}

static List<GraphQLError> fromSpecification(List<Map<String, Object>> specificationMaps) {
return specificationMaps.stream()
.map(GraphqlErrorHelper::fromSpecification).collect(Collectors.toList());
List<GraphQLError> list = FpKit.arrayListSizedTo(specificationMaps);
for (Map<String, Object> specificationMap : specificationMaps) {
list.add(fromSpecification(specificationMap));
}
return list;
}

static GraphQLError fromSpecification(Map<String, Object> specificationMap) {
Expand Down
8 changes: 2 additions & 6 deletions src/main/java/graphql/execution/Execution.java
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,7 @@ private CompletableFuture<ExecutionResult> executeOperation(ExecutionContext exe
MergedSelectionSet fields = fieldCollector.collectFields(
collectorParameters,
operationDefinition.getSelectionSet(),
Optional.ofNullable(executionContext.getGraphQLContext())
.map(graphqlContext -> graphqlContext.getBoolean(ExperimentalApi.ENABLE_INCREMENTAL_SUPPORT))
.orElse(false)
executionContext.hasIncrementalSupport()

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is critical path stuff and is used in a number of places

);

ResultPath path = ResultPath.rootPath();
Expand Down Expand Up @@ -259,9 +257,7 @@ private DataLoaderDispatchStrategy createDataLoaderDispatchStrategy(ExecutionCon
return DataLoaderDispatchStrategy.NO_OP;
}
if (!executionContext.isSubscriptionOperation()) {
boolean deferEnabled = Optional.ofNullable(executionContext.getGraphQLContext())
.map(graphqlContext -> graphqlContext.getBoolean(ExperimentalApi.ENABLE_INCREMENTAL_SUPPORT))
.orElse(false);
boolean deferEnabled = executionContext.hasIncrementalSupport();

// Dedicated strategy for defer support, for safety purposes.
return deferEnabled ?
Expand Down
7 changes: 6 additions & 1 deletion src/main/java/graphql/execution/ExecutionContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -366,9 +366,14 @@ public ResultNodesInfo getResultNodesInfo() {
return resultNodesInfo;
}

@Internal
public boolean hasIncrementalSupport() {
GraphQLContext graphqlContext = getGraphQLContext();
return graphqlContext != null && graphqlContext.getBoolean(ExperimentalApi.ENABLE_INCREMENTAL_SUPPORT);
}

@Internal
public EngineRunningState getEngineRunningState() {
return engineRunningState;
}

}
8 changes: 2 additions & 6 deletions src/main/java/graphql/execution/ExecutionStrategy.java
Original file line number Diff line number Diff line change
Expand Up @@ -288,9 +288,7 @@ private BiConsumer<List<Object>, Throwable> buildFieldValueMap(List<String> fiel
DeferredExecutionSupport createDeferredExecutionSupport(ExecutionContext executionContext, ExecutionStrategyParameters parameters) {
MergedSelectionSet fields = parameters.getFields();

return Optional.ofNullable(executionContext.getGraphQLContext())
.map(graphqlContext -> graphqlContext.getBoolean(ExperimentalApi.ENABLE_INCREMENTAL_SUPPORT))
.orElse(false) ?
return executionContext.hasIncrementalSupport() ?
new DeferredExecutionSupport.DeferredExecutionSupportImpl(
fields,
parameters,
Expand Down Expand Up @@ -919,9 +917,7 @@ protected Object completeValueForObject(ExecutionContext executionContext, Execu
MergedSelectionSet subFields = fieldCollector.collectFields(
collectorParameters,
parameters.getField(),
Optional.ofNullable(executionContext.getGraphQLContext())
.map(graphqlContext -> graphqlContext.getBoolean(ExperimentalApi.ENABLE_INCREMENTAL_SUPPORT))
.orElse(false)
executionContext.hasIncrementalSupport()

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is more critical path - avoids two Optional allocations

);

ExecutionStepInfo newExecutionStepInfo = executionStepInfo.changeTypeWithPreservedNonNull(resolvedObjectType);
Expand Down
22 changes: 12 additions & 10 deletions src/main/java/graphql/execution/ValuesResolverConversion.java
Original file line number Diff line number Diff line change
Expand Up @@ -602,16 +602,18 @@ private static List externalValueToInternalValueForList(
) throws CoercingParseValueException, NonNullableValueCoercedAsNullException {

GraphQLInputType wrappedType = (GraphQLInputType) graphQLList.getWrappedType();
return FpKit.toListOrSingletonList(value)
.stream()
.map(val -> externalValueToInternalValueImpl(
inputInterceptor,
fieldVisibility,
wrappedType,
val,
graphqlContext,
locale))
.collect(toList());
List<Object> listOrSingletonList = FpKit.toListOrSingletonList(value);
List<Object> list = FpKit.arrayListSizedTo(listOrSingletonList);
for (Object val : listOrSingletonList) {
list.add(externalValueToInternalValueImpl(
inputInterceptor,
fieldVisibility,
wrappedType,
val,
graphqlContext,
locale));
}
return list;
}

/**
Expand Down
9 changes: 5 additions & 4 deletions src/main/java/graphql/execution/ValuesResolverLegacy.java
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,11 @@ private static Value<?> handleNumberLegacy(String stringValue) {
private static Value<?> handleListLegacy(Object value, GraphQLList type, GraphQLContext graphqlContext, Locale locale) {
GraphQLType itemType = type.getWrappedType();
if (FpKit.isIterable(value)) {
List<Value> valuesNodes = FpKit.toListOrSingletonList(value)
.stream()
.map(item -> valueToLiteralLegacy(item, itemType, graphqlContext, locale))
.collect(toList());
List<Object> listOrSingletonList = FpKit.toListOrSingletonList(value);
List<Value> valuesNodes = FpKit.arrayListSizedTo(listOrSingletonList);
for (Object item : listOrSingletonList) {
valuesNodes.add(valueToLiteralLegacy(item, itemType, graphqlContext, locale));
}
return ArrayValue.newArrayValue().values(valuesNodes).build();
}
return valueToLiteralLegacy(value, itemType, graphqlContext, locale);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
* The purpose of this class hierarchy is to encapsulate most of the logic for deferring field execution, thus
Expand Down Expand Up @@ -106,19 +106,23 @@ public List<String> getNonDeferredFieldNames(List<String> allFieldNames) {

@Override
public Set<IncrementalCall<? extends IncrementalPayload>> createCalls(ExecutionStrategyParameters executionStrategyParameters) {
return deferredExecutionToFields.keySet().stream()
.map(deferredExecution -> this.createDeferredFragmentCall(deferredExecution, executionStrategyParameters))
.collect(Collectors.toSet());
ImmutableSet<DeferredExecution> deferredExecutions = deferredExecutionToFields.keySet();
Set<IncrementalCall<? extends IncrementalPayload>> set = new HashSet<>(deferredExecutions.size());
for (DeferredExecution deferredExecution : deferredExecutions) {
set.add(this.createDeferredFragmentCall(deferredExecution, executionStrategyParameters));
}
return set;
}

private DeferredFragmentCall createDeferredFragmentCall(DeferredExecution deferredExecution, ExecutionStrategyParameters executionStrategyParameters) {
DeferredCallContext deferredCallContext = new DeferredCallContext();

List<MergedField> mergedFields = deferredExecutionToFields.get(deferredExecution);

List<Supplier<CompletableFuture<DeferredFragmentCall.FieldWithExecutionResult>>> calls = mergedFields.stream()
.map(currentField -> this.createResultSupplier(currentField, deferredCallContext, executionStrategyParameters))
.collect(Collectors.toList());
List<Supplier<CompletableFuture<DeferredFragmentCall.FieldWithExecutionResult>>> calls = FpKit.arrayListSizedTo(mergedFields);
for (MergedField currentField : mergedFields) {
calls.add(this.createResultSupplier(currentField, deferredCallContext, executionStrategyParameters));
}

return new DeferredFragmentCall(
deferredExecution.getLabel(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import graphql.execution.ExecutionContext;
import graphql.execution.ExecutionStrategyParameters;
import graphql.execution.FieldValueInfo;
import graphql.execution.MergedField;
import graphql.schema.DataFetcher;
import graphql.util.LockKit;
import org.dataloader.DataLoaderRegistry;
Expand Down Expand Up @@ -195,10 +196,13 @@ public void fieldFetched(ExecutionContext executionContext,
}

private void increaseCallCounts(int curLevel, ExecutionStrategyParameters parameters) {
int nonDeferredFieldCount = (int) parameters.getFields().getSubFieldsList().stream()
.filter(field -> !field.isDeferred())
.count();

int count = 0;
for (MergedField field : parameters.getFields().getSubFieldsList()) {
if (!field.isDeferred()) {
count++;
}
}
int nonDeferredFieldCount = count;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is more critical path when defer is on

callStack.lock.runLocked(() -> {
callStack.increaseExpectedFetchCount(curLevel, nonDeferredFieldCount);
callStack.increaseHappenedStrategyCalls(curLevel);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package graphql.incremental;

import graphql.ExperimentalApi;
import graphql.util.FpKit;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@ExperimentalApi
public class DelayedIncrementalPartialResultImpl implements DelayedIncrementalPartialResult {
Expand Down Expand Up @@ -44,10 +44,12 @@ public Map<String, Object> toSpecification() {
result.put("extensions", extensions);
}

if(incrementalItems != null) {
result.put("incremental", incrementalItems.stream()
.map(IncrementalPayload::toSpecification)
.collect(Collectors.toList()));
if (incrementalItems != null) {
List<Map<String, Object>> list = FpKit.arrayListSizedTo(incrementalItems);
for (IncrementalPayload incrementalItem : incrementalItems) {
list.add(incrementalItem.toSpecification());
}
result.put("incremental", list);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

critical path when defer is on

}

return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;

@ExperimentalApi
public class IncrementalExecutionResultImpl extends ExecutionResultImpl implements IncrementalExecutionResult {
Expand Down Expand Up @@ -66,11 +65,11 @@ public Map<String, Object> toSpecification() {
map.put("hasNext", hasNext);

if (this.incremental != null) {
map.put("incremental",
this.incremental.stream()
.map(IncrementalPayload::toSpecification)
.collect(Collectors.toCollection(LinkedList::new))
);
LinkedList<Map<String, Object>> linkedList = new LinkedList<>();
for (IncrementalPayload incrementalPayload : this.incremental) {
linkedList.add(incrementalPayload.toSpecification());
}
map.put("incremental", linkedList);
}

return map;
Expand Down
17 changes: 12 additions & 5 deletions src/main/java/graphql/incremental/IncrementalPayload.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import graphql.ExperimentalApi;
import graphql.GraphQLError;
import graphql.execution.ResultPath;
import graphql.util.FpKit;
import org.jspecify.annotations.Nullable;

import java.util.ArrayList;
Expand All @@ -11,8 +12,6 @@
import java.util.Map;
import java.util.Objects;

import static java.util.stream.Collectors.toList;

/**
* Represents a payload that can be resolved after the initial response.
*/
Expand Down Expand Up @@ -80,16 +79,24 @@ public Map<String, Object> toSpecification() {
}

protected Object errorsToSpec(List<GraphQLError> errors) {
return errors.stream().map(GraphQLError::toSpecification).collect(toList());
List<Map<String, Object>> list = FpKit.arrayListSizedTo(errors);
for (GraphQLError error : errors) {
list.add(error.toSpecification());
}
return list;
}

public int hashCode() {
return Objects.hash(path, label, errors, extensions);
}

public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
IncrementalPayload that = (IncrementalPayload) obj;
return Objects.equals(path, that.path) &&
Objects.equals(label, that.label) &&
Expand Down
26 changes: 17 additions & 9 deletions src/main/java/graphql/schema/fetching/LambdaFetchingSupport.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import graphql.Internal;
import graphql.VisibleForTesting;
import graphql.util.FpKit;

import java.lang.invoke.CallSite;
import java.lang.invoke.LambdaMetafactory;
Expand All @@ -17,8 +18,6 @@
import java.util.function.Function;
import java.util.function.Predicate;

import static java.util.stream.Collectors.toList;

@Internal
public class LambdaFetchingSupport {

Expand Down Expand Up @@ -69,9 +68,12 @@ private static Method getCandidateMethod(Class<?> sourceClass, String propertyNa
Predicate<Method> getterPredicate = method -> isGetterNamed(method) && propertyName.equals(mkPropertyNameGetter(method));
List<Method> allGetterMethods = findMethodsForProperty(sourceClass,
getterPredicate);
List<Method> pojoGetterMethods = allGetterMethods.stream()
.filter(LambdaFetchingSupport::isPossiblePojoMethod)
.collect(toList());
List<Method> pojoGetterMethods = FpKit.arrayListSizedTo(allGetterMethods);
for (Method allGetterMethod : allGetterMethods) {
if (isPossiblePojoMethod(allGetterMethod)) {
pojoGetterMethods.add(allGetterMethod);
}
}
if (!pojoGetterMethods.isEmpty()) {
Method method = pojoGetterMethods.get(0);
if (isBooleanGetter(method)) {
Expand All @@ -97,7 +99,13 @@ private static Method checkForSingleParameterPeer(Method candidateMethod, List<M

private static Method findBestBooleanGetter(List<Method> methods) {
// we prefer isX() over getX() if both happen to be present
Optional<Method> isMethod = methods.stream().filter(method -> method.getName().startsWith("is")).findFirst();
Optional<Method> isMethod = Optional.empty();
for (Method method : methods) {
if (method.getName().startsWith("is")) {
isMethod = Optional.of(method);
break;
}
}
return isMethod.orElse(methods.get(0));
}

Expand All @@ -121,9 +129,9 @@ private static List<Method> findMethodsForProperty(Class<?> sourceClass, Predica
currentClass = currentClass.getSuperclass();
}

return methods.stream()
.sorted(Comparator.comparing(Method::getName))
.collect(toList());
List<Method> list = new ArrayList<>(methods);
list.sort(Comparator.comparing(Method::getName));
return list;
}

private static boolean isPossiblePojoMethod(Method method) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,10 @@ public final GraphQLSchema apply(GraphQLSchema schema) {
Set<GraphQLType> markedForRemovalTypes = new HashSet<>();

// query, mutation, and subscription types should not be removed
final Set<String> protectedTypeNames = getOperationTypes(schema).stream()
.map(GraphQLObjectType::getName)
.collect(Collectors.toSet());
final Set<String> protectedTypeNames = new HashSet<>();
for (GraphQLObjectType graphQLObjectType : getOperationTypes(schema)) {
protectedTypeNames.add(graphQLObjectType.getName());
}

beforeTransformationHook.run();

Expand Down
Loading