Skip to content

Commit bbc3e43

Browse files
committed
initial work up of per query/per request scoped context and dispatching instrumentation
1 parent e82a465 commit bbc3e43

38 files changed

+1336
-346
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
version = 7.5.1-SNAPSHOT
22
group = com.graphql-java-kickstart
33

4-
LIB_GRAPHQL_JAVA_VER = 12.0
4+
LIB_GRAPHQL_JAVA_VER = 13.0
55
LIB_JACKSON_VER = 2.9.8

src/main/java/graphql/servlet/BatchExecutionHandler.java

Lines changed: 0 additions & 25 deletions
This file was deleted.

src/main/java/graphql/servlet/DefaultBatchExecutionHandler.java

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/main/java/graphql/servlet/DefaultGraphQLServlet.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package graphql.servlet;
22

3+
import graphql.servlet.core.AbstractGraphQLHttpServlet;
4+
import graphql.servlet.input.GraphQLInvocationInputFactory;
5+
36
public class DefaultGraphQLServlet extends AbstractGraphQLHttpServlet {
47

58
@Override

src/main/java/graphql/servlet/GraphQLBatchedInvocationInput.java

Lines changed: 0 additions & 30 deletions
This file was deleted.

src/main/java/graphql/servlet/GraphQLInvocationInput.java

Lines changed: 0 additions & 54 deletions
This file was deleted.

src/main/java/graphql/servlet/GraphQLQueryInvoker.java

Lines changed: 87 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,26 @@
1111
import graphql.execution.preparsed.NoOpPreparsedDocumentProvider;
1212
import graphql.execution.preparsed.PreparsedDocumentProvider;
1313
import graphql.schema.GraphQLSchema;
14+
import graphql.servlet.core.AbstractGraphQLHttpServlet;
15+
import graphql.servlet.input.BatchInputPreProcessResult;
16+
import graphql.servlet.input.BatchInputPreProcessor;
17+
import graphql.servlet.input.ContextSetting;
18+
import graphql.servlet.input.GraphQLBatchedInvocationInput;
19+
import graphql.servlet.input.GraphQLSingleInvocationInput;
20+
import graphql.servlet.input.NoOpBatchInputPreProcessor;
1421

1522
import javax.security.auth.Subject;
23+
import javax.servlet.http.HttpServletRequest;
1624
import javax.servlet.http.HttpServletResponse;
25+
import java.io.IOException;
1726
import java.io.Writer;
1827
import java.security.AccessController;
1928
import java.security.PrivilegedAction;
20-
import java.util.ArrayList;
29+
import java.util.Iterator;
2130
import java.util.List;
31+
import java.util.concurrent.CompletableFuture;
2232
import java.util.function.Supplier;
33+
import java.util.stream.Collectors;
2334

2435
/**
2536
* @author Andrew Potter
@@ -29,52 +40,76 @@ public class GraphQLQueryInvoker {
2940
private final Supplier<ExecutionStrategyProvider> getExecutionStrategyProvider;
3041
private final Supplier<Instrumentation> getInstrumentation;
3142
private final Supplier<PreparsedDocumentProvider> getPreparsedDocumentProvider;
32-
private final Supplier<DataLoaderDispatcherInstrumentationOptions> dataLoaderDispatcherInstrumentationOptionsSupplier;
33-
private final BatchExecutionHandler batchExecutionHandler;
43+
private final Supplier<BatchInputPreProcessor> batchInputPreProcessor;
44+
private final Supplier<DataLoaderDispatcherInstrumentationOptions> optionsSupplier;
3445

35-
protected GraphQLQueryInvoker(Supplier<ExecutionStrategyProvider> getExecutionStrategyProvider, Supplier<Instrumentation> getInstrumentation, Supplier<PreparsedDocumentProvider> getPreparsedDocumentProvider, Supplier<DataLoaderDispatcherInstrumentationOptions> optionsSupplier, BatchExecutionHandler batchExecutionHandler) {
46+
protected GraphQLQueryInvoker(Supplier<ExecutionStrategyProvider> getExecutionStrategyProvider, Supplier<Instrumentation> getInstrumentation,
47+
Supplier<PreparsedDocumentProvider> getPreparsedDocumentProvider,
48+
Supplier<BatchInputPreProcessor> batchInputPreProcessor,
49+
Supplier<DataLoaderDispatcherInstrumentationOptions> optionsSupplier) {
3650
this.getExecutionStrategyProvider = getExecutionStrategyProvider;
3751
this.getInstrumentation = getInstrumentation;
3852
this.getPreparsedDocumentProvider = getPreparsedDocumentProvider;
39-
this.dataLoaderDispatcherInstrumentationOptionsSupplier = optionsSupplier;
40-
this.batchExecutionHandler = batchExecutionHandler;
53+
this.batchInputPreProcessor = batchInputPreProcessor;
54+
this.optionsSupplier = optionsSupplier;
4155
}
4256

4357
public ExecutionResult query(GraphQLSingleInvocationInput singleInvocationInput) {
44-
return query(singleInvocationInput, singleInvocationInput.getExecutionInput());
58+
return queryAsync(singleInvocationInput, getInstrumentation).join();
4559
}
4660

47-
public void query(GraphQLBatchedInvocationInput batchedInvocationInput, HttpServletResponse response, GraphQLObjectMapper graphQLObjectMapper) {
48-
batchExecutionHandler.handleBatch(batchedInvocationInput, response, graphQLObjectMapper, this::query);
61+
private CompletableFuture<ExecutionResult> queryAsync(GraphQLSingleInvocationInput singleInvocationInput, Supplier<Instrumentation> configuredInstrumentation) {
62+
return query(singleInvocationInput, configuredInstrumentation, singleInvocationInput.getExecutionInput());
4963
}
5064

51-
private GraphQL newGraphQL(GraphQLSchema schema, Object context) {
65+
public void query(GraphQLBatchedInvocationInput batchedInvocationInput, ContextSetting contextSetting, HttpServletRequest request, HttpServletResponse response,
66+
GraphQLObjectMapper graphQLObjectMapper) {
67+
BatchInputPreProcessResult processedInput = batchInputPreProcessor.get().preProcessBatch(batchedInvocationInput, request, response);
68+
if (processedInput.isExecutable()) {
69+
response.setContentType(AbstractGraphQLHttpServlet.APPLICATION_JSON_UTF8);
70+
response.setStatus(AbstractGraphQLHttpServlet.STATUS_OK);
71+
List<ExecutionInput> executionIds = batchedInvocationInput.getExecutionInputs().stream()
72+
.map(GraphQLSingleInvocationInput::getExecutionInput)
73+
.collect(Collectors.toList());
74+
Supplier<Instrumentation> configuredInstrumentation = contextSetting.configureInstrumentationForContext(getInstrumentation, executionIds,
75+
optionsSupplier.get());
76+
Iterator<CompletableFuture<ExecutionResult>> resultIter = processedInput.getBatchedInvocationInput().getExecutionInputs().stream()
77+
.map(input -> this.queryAsync(input, configuredInstrumentation))
78+
//We want eager eval
79+
.collect(Collectors.toList())
80+
.iterator();
81+
82+
try {
83+
Writer writer = response.getWriter();
84+
writer.write("[");
85+
while (resultIter.hasNext()) {
86+
ExecutionResult current = resultIter.next().join();
87+
writer.write(graphQLObjectMapper.serializeResultAsJson(current));
88+
if (resultIter.hasNext()) {
89+
writer.write(",");
90+
}
91+
}
92+
writer.write("]");
93+
} catch (IOException ex) {
94+
throw new RuntimeException(ex);
95+
}
96+
}
97+
//TODO should we check if the batch pre processor set the status in an else? if not what would we set?
98+
}
99+
100+
private GraphQL newGraphQL(GraphQLSchema schema, Supplier<Instrumentation> configuredInstrumentation) {
52101
ExecutionStrategyProvider executionStrategyProvider = getExecutionStrategyProvider.get();
53-
return GraphQL.newGraphQL(schema)
102+
GraphQL.Builder builder = GraphQL.newGraphQL(schema)
54103
.queryExecutionStrategy(executionStrategyProvider.getQueryExecutionStrategy())
55104
.mutationExecutionStrategy(executionStrategyProvider.getMutationExecutionStrategy())
56105
.subscriptionExecutionStrategy(executionStrategyProvider.getSubscriptionExecutionStrategy())
57-
.instrumentation(getInstrumentation(context))
58-
.preparsedDocumentProvider(getPreparsedDocumentProvider.get())
59-
.build();
60-
}
61-
62-
protected Instrumentation getInstrumentation(Object context) {
63-
if (context instanceof GraphQLContext) {
64-
return ((GraphQLContext) context).getDataLoaderRegistry()
65-
.map(registry -> {
66-
Instrumentation instrumentation = getInstrumentation.get();
67-
if (!containsDispatchInstrumentation(instrumentation)) {
68-
List<Instrumentation> instrumentations = new ArrayList<>();
69-
instrumentations.add(instrumentation);
70-
instrumentations.add(new DataLoaderDispatcherInstrumentation(dataLoaderDispatcherInstrumentationOptionsSupplier.get()));
71-
instrumentation = new ChainedInstrumentation(instrumentations);
72-
}
73-
return instrumentation;
74-
})
75-
.orElse(getInstrumentation.get());
76-
}
77-
return getInstrumentation.get();
106+
.preparsedDocumentProvider(getPreparsedDocumentProvider.get());
107+
Instrumentation instrumentation = configuredInstrumentation.get();
108+
builder.instrumentation(instrumentation);
109+
if (containsDispatchInstrumentation(instrumentation)) {
110+
builder.doNotAddDefaultInstrumentations();
111+
}
112+
return builder.build();
78113
}
79114

80115
private boolean containsDispatchInstrumentation(Instrumentation instrumentation) {
@@ -84,22 +119,22 @@ private boolean containsDispatchInstrumentation(Instrumentation instrumentation)
84119
return instrumentation instanceof DataLoaderDispatcherInstrumentation;
85120
}
86121

87-
private ExecutionResult query(GraphQLInvocationInput invocationInput, ExecutionInput executionInput) {
122+
private CompletableFuture<ExecutionResult> query(GraphQLSingleInvocationInput invocationInput, Supplier<Instrumentation> configuredInstrumentation, ExecutionInput executionInput) {
88123
if (Subject.getSubject(AccessController.getContext()) == null && invocationInput.getSubject().isPresent()) {
89-
return Subject.doAs(invocationInput.getSubject().get(), (PrivilegedAction<ExecutionResult>) () -> {
124+
return Subject.doAs(invocationInput.getSubject().get(), (PrivilegedAction<CompletableFuture<ExecutionResult>>) () -> {
90125
try {
91-
return query(invocationInput.getSchema(), executionInput);
126+
return query(invocationInput.getSchema(), executionInput, configuredInstrumentation);
92127
} catch (Exception e) {
93128
throw new RuntimeException(e);
94129
}
95130
});
96131
}
97132

98-
return query(invocationInput.getSchema(), executionInput);
133+
return query(invocationInput.getSchema(), executionInput, configuredInstrumentation);
99134
}
100135

101-
private ExecutionResult query(GraphQLSchema schema, ExecutionInput executionInput) {
102-
return newGraphQL(schema, executionInput.getContext()).execute(executionInput);
136+
private CompletableFuture<ExecutionResult> query(GraphQLSchema schema, ExecutionInput executionInput, Supplier<Instrumentation> configuredInstrumentation) {
137+
return newGraphQL(schema, configuredInstrumentation).executeAsync(executionInput);
103138
}
104139

105140
public static Builder newBuilder() {
@@ -110,8 +145,9 @@ public static class Builder {
110145
private Supplier<ExecutionStrategyProvider> getExecutionStrategyProvider = DefaultExecutionStrategyProvider::new;
111146
private Supplier<Instrumentation> getInstrumentation = () -> SimpleInstrumentation.INSTANCE;
112147
private Supplier<PreparsedDocumentProvider> getPreparsedDocumentProvider = () -> NoOpPreparsedDocumentProvider.INSTANCE;
148+
private Supplier<BatchInputPreProcessor> batchInputPreProcessor = () -> new NoOpBatchInputPreProcessor();
113149
private Supplier<DataLoaderDispatcherInstrumentationOptions> dataLoaderDispatcherInstrumentationOptionsSupplier = DataLoaderDispatcherInstrumentationOptions::newOptions;
114-
private BatchExecutionHandler batchExecutionHandler = new DefaultBatchExecutionHandler();
150+
115151

116152
public Builder withExecutionStrategyProvider(ExecutionStrategyProvider provider) {
117153
return withExecutionStrategyProvider(() -> provider);
@@ -143,9 +179,16 @@ public Builder with(List<Instrumentation> instrumentations) {
143179
return this;
144180
}
145181

146-
public Builder withBatchExeuctionHandler(BatchExecutionHandler batchExeuctionHandler) {
147-
if (batchExeuctionHandler != null) {
148-
this.batchExecutionHandler = batchExeuctionHandler;
182+
public Builder withBatchInputPreProcessor(BatchInputPreProcessor batchInputPreProcessor) {
183+
if (batchInputPreProcessor != null) {
184+
this.batchInputPreProcessor = () -> batchInputPreProcessor;
185+
}
186+
return this;
187+
}
188+
189+
public Builder withBatchInputPreProcessor(Supplier<BatchInputPreProcessor> batchInputPreProcessor) {
190+
if (batchInputPreProcessor != null) {
191+
this.batchInputPreProcessor = batchInputPreProcessor;
149192
}
150193
return this;
151194
}
@@ -169,7 +212,8 @@ public Builder withDataLoaderDispatcherInstrumentationOptions(Supplier<DataLoade
169212
}
170213

171214
public GraphQLQueryInvoker build() {
172-
return new GraphQLQueryInvoker(getExecutionStrategyProvider, getInstrumentation, getPreparsedDocumentProvider, dataLoaderDispatcherInstrumentationOptionsSupplier, batchExecutionHandler);
215+
return new GraphQLQueryInvoker(getExecutionStrategyProvider, getInstrumentation, getPreparsedDocumentProvider, batchInputPreProcessor,
216+
dataLoaderDispatcherInstrumentationOptionsSupplier);
173217
}
174218
}
175219
}

src/main/java/graphql/servlet/GraphQLSingleInvocationInput.java

Lines changed: 0 additions & 23 deletions
This file was deleted.

0 commit comments

Comments
 (0)