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
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
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 @@ -283,9 +283,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 @@ -908,9 +906,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
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 @@ -18,14 +18,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 @@ -107,19 +107,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
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
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
Loading