Skip to content

Commit a0c0f49

Browse files
committed
Build GraphQL on the fly after all
1 parent 6465fa8 commit a0c0f49

File tree

8 files changed

+101
-43
lines changed

8 files changed

+101
-43
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package graphql.kickstart.execution;
2+
3+
import graphql.ExecutionInput;
4+
import graphql.GraphQL;
5+
import graphql.execution.instrumentation.Instrumentation;
6+
import graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentationOptions;
7+
import graphql.kickstart.execution.config.GraphQLBuilder;
8+
import graphql.kickstart.execution.input.GraphQLBatchedInvocationInput;
9+
import graphql.kickstart.execution.input.GraphQLSingleInvocationInput;
10+
import java.util.List;
11+
import java.util.function.Supplier;
12+
13+
public class BatchedDataLoaderGraphQLBuilder {
14+
15+
private final Supplier<DataLoaderDispatcherInstrumentationOptions> optionsSupplier;
16+
17+
public BatchedDataLoaderGraphQLBuilder(Supplier<DataLoaderDispatcherInstrumentationOptions> optionsSupplier) {
18+
if (optionsSupplier != null) {
19+
this.optionsSupplier = optionsSupplier;
20+
} else {
21+
this.optionsSupplier = DataLoaderDispatcherInstrumentationOptions::newOptions;
22+
}
23+
}
24+
25+
GraphQL newGraphQL(GraphQLBatchedInvocationInput invocationInput, GraphQLBuilder graphQLBuilder) {
26+
Supplier<Instrumentation> supplier = augment(invocationInput, graphQLBuilder.getInstrumentationSupplier());
27+
return invocationInput.getInvocationInputs().stream().findFirst()
28+
.map(GraphQLSingleInvocationInput::getSchema)
29+
.map(schema -> graphQLBuilder.build(schema, supplier))
30+
.orElseThrow(() -> new IllegalArgumentException("Batched invocation input must contain at least one query"));
31+
}
32+
33+
private Supplier<Instrumentation> augment(
34+
GraphQLBatchedInvocationInput batchedInvocationInput,
35+
Supplier<Instrumentation> instrumentationSupplier
36+
) {
37+
List<ExecutionInput> executionInputs = batchedInvocationInput.getExecutionInputs();
38+
return batchedInvocationInput.getContextSetting()
39+
.configureInstrumentationForContext(instrumentationSupplier, executionInputs, optionsSupplier.get());
40+
}
41+
42+
}

graphql-java-kickstart/src/main/java/graphql/kickstart/execution/GraphQLInvoker.java

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,25 @@
44

55
import graphql.ExecutionResult;
66
import graphql.GraphQL;
7-
import graphql.kickstart.execution.context.ContextSetting;
7+
import graphql.kickstart.execution.config.GraphQLBuilder;
88
import graphql.kickstart.execution.input.GraphQLBatchedInvocationInput;
99
import graphql.kickstart.execution.input.GraphQLInvocationInput;
1010
import graphql.kickstart.execution.input.GraphQLSingleInvocationInput;
1111
import java.util.List;
1212
import java.util.concurrent.CompletableFuture;
13-
import java.util.stream.Collectors;
1413
import lombok.AllArgsConstructor;
1514
import lombok.RequiredArgsConstructor;
1615

1716
@AllArgsConstructor
1817
@RequiredArgsConstructor
1918
public class GraphQLInvoker {
2019

21-
private final GraphQL graphQL;
20+
private final GraphQLBuilder graphQLBuilder;
21+
private final BatchedDataLoaderGraphQLBuilder batchedDataLoaderGraphQLBuilder;
2222
private GraphQLInvokerProxy proxy = GraphQL::executeAsync;
2323

2424
public CompletableFuture<ExecutionResult> executeAsync(GraphQLSingleInvocationInput invocationInput) {
25+
GraphQL graphQL = graphQLBuilder.build(invocationInput.getSchema());
2526
return proxy.executeAsync(graphQL, invocationInput.getExecutionInput());
2627
}
2728

@@ -30,24 +31,19 @@ public GraphQLQueryResult query(GraphQLInvocationInput invocationInput) {
3031
return GraphQLQueryResult.create(query((GraphQLSingleInvocationInput) invocationInput));
3132
}
3233
GraphQLBatchedInvocationInput batchedInvocationInput = (GraphQLBatchedInvocationInput) invocationInput;
33-
return GraphQLQueryResult
34-
.create(query(batchedInvocationInput.getExecutionInputs(), batchedInvocationInput.getContextSetting()));
34+
return GraphQLQueryResult.create(query(batchedInvocationInput));
3535
}
3636

3737
private ExecutionResult query(GraphQLSingleInvocationInput singleInvocationInput) {
3838
return executeAsync(singleInvocationInput).join();
3939
}
4040

41-
private List<ExecutionResult> query(List<GraphQLSingleInvocationInput> batchedInvocationInput,
42-
ContextSetting contextSetting) {
43-
// List<ExecutionInput> executionIds = batchedInvocationInput.stream()
44-
// .map(GraphQLSingleInvocationInput::getExecutionInput)
45-
// .collect(Collectors.toList());
46-
// Supplier<Instrumentation> configuredInstrumentation = contextSetting
47-
// .configureInstrumentationForContext(getInstrumentation, executionIds, optionsSupplier.get());
48-
return batchedInvocationInput.stream()
49-
.map(this::executeAsync)
41+
private List<ExecutionResult> query(GraphQLBatchedInvocationInput batchedInvocationInput) {
42+
GraphQL graphQL = batchedDataLoaderGraphQLBuilder.newGraphQL(batchedInvocationInput, graphQLBuilder);
43+
return batchedInvocationInput.getExecutionInputs().stream()
44+
.map(executionInput -> proxy.executeAsync(graphQL, executionInput))
5045
.map(CompletableFuture::join)
5146
.collect(toList());
5247
}
5348
}
49+

graphql-java-kickstart/src/main/java/graphql/kickstart/execution/GraphQLQueryInvoker.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public GraphQLQueryResult query(GraphQLInvocationInput invocationInput) {
5454
return GraphQLQueryResult.create(query((GraphQLSingleInvocationInput) invocationInput));
5555
}
5656
GraphQLBatchedInvocationInput batchedInvocationInput = (GraphQLBatchedInvocationInput) invocationInput;
57-
return GraphQLQueryResult.create(query(batchedInvocationInput.getExecutionInputs(), batchedInvocationInput.getContextSetting()));
57+
return GraphQLQueryResult.create(query(batchedInvocationInput.getInvocationInputs(), batchedInvocationInput.getContextSetting()));
5858
}
5959

6060
public ExecutionResult query(GraphQLSingleInvocationInput singleInvocationInput) {

graphql-java-kickstart/src/main/java/graphql/kickstart/execution/config/GraphQLBuilder.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,33 @@
99
import graphql.execution.preparsed.PreparsedDocumentProvider;
1010
import graphql.schema.GraphQLSchema;
1111
import java.util.function.Supplier;
12+
import lombok.Getter;
1213

1314
public class GraphQLBuilder {
1415

1516
private Supplier<ExecutionStrategyProvider> executionStrategyProviderSupplier = DefaultExecutionStrategyProvider::new;
1617
private Supplier<PreparsedDocumentProvider> preparsedDocumentProviderSupplier = () -> NoOpPreparsedDocumentProvider.INSTANCE;
18+
@Getter
1719
private Supplier<Instrumentation> instrumentationSupplier = () -> SimpleInstrumentation.INSTANCE;
1820

1921
public GraphQLBuilder executionStrategyProvider(Supplier<ExecutionStrategyProvider> supplier) {
20-
executionStrategyProviderSupplier = supplier;
22+
if (supplier != null) {
23+
executionStrategyProviderSupplier = supplier;
24+
}
2125
return this;
2226
}
2327

2428
public GraphQLBuilder preparsedDocumentProvider(Supplier<PreparsedDocumentProvider> supplier) {
25-
preparsedDocumentProviderSupplier = supplier;
29+
if (supplier != null) {
30+
preparsedDocumentProviderSupplier = supplier;
31+
}
2632
return this;
2733
}
2834

2935
public GraphQLBuilder instrumentation(Supplier<Instrumentation> supplier) {
30-
instrumentationSupplier = supplier;
36+
if (supplier != null) {
37+
instrumentationSupplier = supplier;
38+
}
3139
return this;
3240
}
3341

@@ -36,13 +44,17 @@ public GraphQL build(GraphQLSchemaProvider schemaProvider) {
3644
}
3745

3846
public GraphQL build(GraphQLSchema schema) {
47+
return build(schema, instrumentationSupplier);
48+
}
49+
50+
public GraphQL build(GraphQLSchema schema, Supplier<Instrumentation> configuredInstrumentationSupplier) {
3951
ExecutionStrategyProvider executionStrategyProvider = executionStrategyProviderSupplier.get();
4052
GraphQL.Builder builder = GraphQL.newGraphQL(schema)
4153
.queryExecutionStrategy(executionStrategyProvider.getQueryExecutionStrategy())
4254
.mutationExecutionStrategy(executionStrategyProvider.getMutationExecutionStrategy())
4355
.subscriptionExecutionStrategy(executionStrategyProvider.getSubscriptionExecutionStrategy())
4456
.preparsedDocumentProvider(preparsedDocumentProviderSupplier.get());
45-
Instrumentation instrumentation = instrumentationSupplier.get();
57+
Instrumentation instrumentation = configuredInstrumentationSupplier.get();
4658
builder.instrumentation(instrumentation);
4759
if (containsDispatchInstrumentation(instrumentation)) {
4860
builder.doNotAddDefaultInstrumentations();
Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
package graphql.kickstart.execution.input;
22

3+
import static java.util.stream.Collectors.toList;
4+
5+
import graphql.ExecutionInput;
36
import graphql.kickstart.execution.context.ContextSetting;
4-
import graphql.kickstart.execution.input.GraphQLInvocationInput;
5-
import graphql.kickstart.execution.input.GraphQLSingleInvocationInput;
67
import java.util.List;
78

89
/**
910
* Interface representing a batched input.
1011
*/
1112
public interface GraphQLBatchedInvocationInput extends GraphQLInvocationInput {
1213

13-
/**
14-
* @return each individual input in the batch, configured with a context.
15-
*/
16-
List<GraphQLSingleInvocationInput> getExecutionInputs();
14+
/**
15+
* @return each individual input in the batch, configured with a context.
16+
*/
17+
List<GraphQLSingleInvocationInput> getInvocationInputs();
18+
19+
default List<ExecutionInput> getExecutionInputs() {
20+
return getInvocationInputs().stream()
21+
.map(GraphQLSingleInvocationInput::getExecutionInput)
22+
.collect(toList());
23+
}
1724

18-
ContextSetting getContextSetting();
25+
ContextSetting getContextSetting();
1926

2027
}

graphql-java-kickstart/src/main/java/graphql/kickstart/execution/input/PerQueryBatchedInvocationInput.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@
1515
*/
1616
@Getter
1717
public class PerQueryBatchedInvocationInput implements GraphQLBatchedInvocationInput {
18-
private final List<GraphQLSingleInvocationInput> executionInputs;
18+
19+
private final List<GraphQLSingleInvocationInput> invocationInputs;
1920
private final ContextSetting contextSetting;
2021

2122
public PerQueryBatchedInvocationInput(List<GraphQLRequest> requests, GraphQLSchema schema, Supplier<GraphQLContext> contextSupplier, Object root, ContextSetting contextSetting) {
22-
executionInputs = requests.stream()
23+
invocationInputs = requests.stream()
2324
.map(request -> new GraphQLSingleInvocationInput(request, schema, contextSupplier.get(), root)).collect(Collectors.toList());
2425
this.contextSetting = contextSetting;
2526
}

graphql-java-kickstart/src/main/java/graphql/kickstart/execution/input/PerRequestBatchedInvocationInput.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@
1515
@Getter
1616
public class PerRequestBatchedInvocationInput implements GraphQLBatchedInvocationInput {
1717

18-
private final List<GraphQLSingleInvocationInput> executionInputs;
18+
private final List<GraphQLSingleInvocationInput> invocationInputs;
1919
private final ContextSetting contextSetting;
2020

2121
public PerRequestBatchedInvocationInput(List<GraphQLRequest> requests, GraphQLSchema schema,
2222
Supplier<GraphQLContext> contextSupplier, Object root, ContextSetting contextSetting) {
2323
GraphQLContext context = contextSupplier.get();
24-
executionInputs = requests.stream().map(request -> new GraphQLSingleInvocationInput(request, schema, context, root))
24+
invocationInputs = requests.stream().map(request -> new GraphQLSingleInvocationInput(request, schema, context, root))
2525
.collect(Collectors.toList());
2626
this.contextSetting = contextSetting;
2727
}
Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
package graphql.servlet;
22

3+
import graphql.kickstart.execution.input.GraphQLBatchedInvocationInput;
34
import graphql.servlet.input.BatchInputPreProcessResult;
45
import graphql.servlet.input.BatchInputPreProcessor;
5-
import graphql.kickstart.execution.input.GraphQLBatchedInvocationInput;
6-
76
import javax.servlet.http.HttpServletRequest;
87
import javax.servlet.http.HttpServletResponse;
98

109
public class TestBatchInputPreProcessor implements BatchInputPreProcessor {
1110

12-
public static String BATCH_ERROR_MESSAGE = "Batch limit exceeded";
11+
public static String BATCH_ERROR_MESSAGE = "Batch limit exceeded";
1312

14-
@Override
15-
public BatchInputPreProcessResult preProcessBatch(GraphQLBatchedInvocationInput batchedInvocationInput, HttpServletRequest request,
16-
HttpServletResponse response) {
17-
BatchInputPreProcessResult preProcessResult;
18-
if (batchedInvocationInput.getExecutionInputs().size() > 2) {
19-
preProcessResult = new BatchInputPreProcessResult(400, BATCH_ERROR_MESSAGE);
20-
} else {
21-
preProcessResult = new BatchInputPreProcessResult(batchedInvocationInput);
22-
}
23-
return preProcessResult;
13+
@Override
14+
public BatchInputPreProcessResult preProcessBatch(GraphQLBatchedInvocationInput batchedInvocationInput,
15+
HttpServletRequest request,
16+
HttpServletResponse response) {
17+
BatchInputPreProcessResult preProcessResult;
18+
if (batchedInvocationInput.getExecutionInputs().size() > 2) {
19+
preProcessResult = new BatchInputPreProcessResult(400, BATCH_ERROR_MESSAGE);
20+
} else {
21+
preProcessResult = new BatchInputPreProcessResult(batchedInvocationInput);
2422
}
23+
return preProcessResult;
24+
}
2525
}

0 commit comments

Comments
 (0)