graphql.execution.nextgen.BatchedExecutionStrategy Maven / Gradle / Ivy
package graphql.execution.nextgen;
import graphql.Assert;
import graphql.Internal;
import graphql.execution.Async;
import graphql.execution.ExecutionContext;
import graphql.execution.ExecutionStepInfo;
import graphql.execution.ExecutionStepInfoFactory;
import graphql.execution.MergedField;
import graphql.execution.nextgen.result.ExecutionResultMultiZipper;
import graphql.execution.nextgen.result.ExecutionResultNode;
import graphql.execution.nextgen.result.ExecutionResultZipper;
import graphql.execution.nextgen.result.NamedResultNode;
import graphql.execution.nextgen.result.ObjectExecutionResultNode;
import graphql.execution.nextgen.result.ObjectExecutionResultNode.RootExecutionResultNode;
import graphql.execution.nextgen.result.ResultNodesUtil;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
@Internal
public class BatchedExecutionStrategy implements ExecutionStrategy {
ExecutionStepInfoFactory executionInfoFactory;
ValueFetcher valueFetcher;
ResultNodesCreator resultNodesCreator = new ResultNodesCreator();
private final ExecutionContext executionContext;
private FetchedValueAnalyzer fetchedValueAnalyzer;
public BatchedExecutionStrategy(ExecutionContext executionContext) {
this.executionContext = executionContext;
this.fetchedValueAnalyzer = new FetchedValueAnalyzer(executionContext);
this.valueFetcher = new ValueFetcher(executionContext);
this.executionInfoFactory = new ExecutionStepInfoFactory();
}
public CompletableFuture execute(FieldSubSelection fieldSubSelection) {
CompletableFuture rootMono = fetchSubSelection(fieldSubSelection).thenApply(RootExecutionResultNode::new);
return rootMono
.thenCompose(rootNode -> {
ExecutionResultMultiZipper unresolvedNodes = ResultNodesUtil.getUnresolvedNodes(rootNode);
return nextStep(unresolvedNodes);
})
.thenApply(finalZipper -> finalZipper.toRootNode())
.thenApply(RootExecutionResultNode.class::cast);
}
private CompletableFuture> fetchSubSelection(FieldSubSelection fieldSubSelection) {
CompletableFuture> fetchedValueAnalysisFlux = fetchAndAnalyze(fieldSubSelection);
return fetchedValueAnalysisFluxToNodes(fetchedValueAnalysisFlux);
}
private CompletableFuture> fetchedValueAnalysisFluxToNodes(CompletableFuture> fetchedValueAnalysisFlux) {
return Async.map(fetchedValueAnalysisFlux,
fetchedValueAnalysis -> new NamedResultNode(fetchedValueAnalysis.getName(), resultNodesCreator.createResultNode(fetchedValueAnalysis)));
}
private CompletableFuture nextStep(ExecutionResultMultiZipper multizipper) {
ExecutionResultMultiZipper nextUnresolvedNodes = ResultNodesUtil.getUnresolvedNodes(multizipper.toRootNode());
if (nextUnresolvedNodes.getZippers().size() == 0) {
return CompletableFuture.completedFuture(nextUnresolvedNodes);
}
List groups = groupNodesIntoBatches(nextUnresolvedNodes);
return nextStepImpl(groups).thenCompose(this::nextStep);
}
// all multizipper have the same root
private CompletableFuture nextStepImpl(List unresolvedNodes) {
Assert.assertNotEmpty(unresolvedNodes, "unresolvedNodes can't be empty");
ExecutionResultNode commonRoot = unresolvedNodes.get(0).getCommonRoot();
CompletableFuture>> listListCF = Async.flatMap(unresolvedNodes,
executionResultMultiZipper -> fetchAndAnalyze(executionResultMultiZipper.getZippers()));
return Common.flatList(listListCF)
.thenApply(zippers -> new ExecutionResultMultiZipper(commonRoot, zippers));
}
private List groupNodesIntoBatches(ExecutionResultMultiZipper unresolvedZipper) {
Map
© 2015 - 2025 Weber Informatics LLC | Privacy Policy