Skip to content

Commit 6f71436

Browse files
authored
State is passed explicitly to instrumentation and parameters are NOT mutated (#2769)
* Another WIP PR that shows how we could transition to the new idea of passing in state to the instrumentation fields * Opps didnt write it right * Start of work to have instrumentation state parameters passed in explicitly * Javadoc error * Added ChainedInstrumentation updates and deprecated all the old methods. * Use jetbrains annotations and also fix merge conflict
1 parent 532d6bb commit 6f71436

29 files changed

Lines changed: 1505 additions & 173 deletions

‎src/main/java/graphql/GraphQL.java‎

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import graphql.execution.instrumentation.Instrumentation;
1717
import graphql.execution.instrumentation.InstrumentationContext;
1818
import graphql.execution.instrumentation.InstrumentationState;
19+
import graphql.execution.instrumentation.NoContextChainedInstrumentation;
1920
import graphql.execution.instrumentation.SimpleInstrumentation;
2021
import graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentation;
2122
import graphql.execution.instrumentation.parameters.InstrumentationCreateStateParameters;
@@ -46,6 +47,7 @@
4647
import static graphql.Assert.assertNotNull;
4748
import static graphql.execution.ExecutionIdProvider.DEFAULT_EXECUTION_ID_PROVIDER;
4849
import static graphql.execution.instrumentation.SimpleInstrumentationContext.completeInstrumentationCtxCF;
50+
import static graphql.execution.instrumentation.SimpleInstrumentationContext.nonNullCtx;
4951

5052
/**
5153
* This class is where all graphql-java query execution begins. It combines the objects that are needed
@@ -512,22 +514,22 @@ public CompletableFuture<ExecutionResult> executeAsync(ExecutionInput executionI
512514
InstrumentationState instrumentationState = instrumentation.createState(new InstrumentationCreateStateParameters(this.graphQLSchema, executionInput));
513515

514516
InstrumentationExecutionParameters inputInstrumentationParameters = new InstrumentationExecutionParameters(executionInput, this.graphQLSchema, instrumentationState);
515-
executionInput = instrumentation.instrumentExecutionInput(executionInput, inputInstrumentationParameters);
517+
executionInput = instrumentation.instrumentExecutionInput(executionInput, inputInstrumentationParameters, instrumentationState);
516518

517519
CompletableFuture<ExecutionResult> beginExecutionCF = new CompletableFuture<>();
518520
InstrumentationExecutionParameters instrumentationParameters = new InstrumentationExecutionParameters(executionInput, this.graphQLSchema, instrumentationState);
519-
InstrumentationContext<ExecutionResult> executionInstrumentation = instrumentation.beginExecution(instrumentationParameters);
521+
InstrumentationContext<ExecutionResult> executionInstrumentation = nonNullCtx(instrumentation.beginExecution(instrumentationParameters, instrumentationState));
520522
executionInstrumentation.onDispatched(beginExecutionCF);
521523

522-
GraphQLSchema graphQLSchema = instrumentation.instrumentSchema(this.graphQLSchema, instrumentationParameters);
524+
GraphQLSchema graphQLSchema = instrumentation.instrumentSchema(this.graphQLSchema, instrumentationParameters, instrumentationState);
523525

524526
CompletableFuture<ExecutionResult> executionResult = parseValidateAndExecute(executionInput, graphQLSchema, instrumentationState);
525527
//
526528
// finish up instrumentation
527529
executionResult = executionResult.whenComplete(completeInstrumentationCtxCF(executionInstrumentation, beginExecutionCF));
528530
//
529531
// allow instrumentation to tweak the result
530-
executionResult = executionResult.thenCompose(result -> instrumentation.instrumentExecutionResult(result, instrumentationParameters));
532+
executionResult = executionResult.thenCompose(result -> instrumentation.instrumentExecutionResult(result, instrumentationParameters, instrumentationState));
531533
return executionResult;
532534
} catch (AbortExecutionException abortException) {
533535
return CompletableFuture.completedFuture(abortException.toExecutionResult());
@@ -598,27 +600,27 @@ private PreparsedDocumentEntry parseAndValidate(AtomicReference<ExecutionInput>
598600

599601
private ParseAndValidateResult parse(ExecutionInput executionInput, GraphQLSchema graphQLSchema, InstrumentationState instrumentationState) {
600602
InstrumentationExecutionParameters parameters = new InstrumentationExecutionParameters(executionInput, graphQLSchema, instrumentationState);
601-
InstrumentationContext<Document> parseInstrumentation = instrumentation.beginParse(parameters);
603+
InstrumentationContext<Document> parseInstrumentationCtx = nonNullCtx(instrumentation.beginParse(parameters, instrumentationState));
602604
CompletableFuture<Document> documentCF = new CompletableFuture<>();
603-
parseInstrumentation.onDispatched(documentCF);
605+
parseInstrumentationCtx.onDispatched(documentCF);
604606

605607
ParseAndValidateResult parseResult = ParseAndValidate.parse(executionInput);
606608
if (parseResult.isFailure()) {
607-
parseInstrumentation.onCompleted(null, parseResult.getSyntaxException());
609+
parseInstrumentationCtx.onCompleted(null, parseResult.getSyntaxException());
608610
return parseResult;
609611
} else {
610612
documentCF.complete(parseResult.getDocument());
611-
parseInstrumentation.onCompleted(parseResult.getDocument(), null);
613+
parseInstrumentationCtx.onCompleted(parseResult.getDocument(), null);
612614

613615
DocumentAndVariables documentAndVariables = parseResult.getDocumentAndVariables();
614-
documentAndVariables = instrumentation.instrumentDocumentAndVariables(documentAndVariables, parameters);
616+
documentAndVariables = instrumentation.instrumentDocumentAndVariables(documentAndVariables, parameters, instrumentationState);
615617
return ParseAndValidateResult.newResult()
616618
.document(documentAndVariables.getDocument()).variables(documentAndVariables.getVariables()).build();
617619
}
618620
}
619621

620622
private List<ValidationError> validate(ExecutionInput executionInput, Document document, GraphQLSchema graphQLSchema, InstrumentationState instrumentationState) {
621-
InstrumentationContext<List<ValidationError>> validationCtx = instrumentation.beginValidation(new InstrumentationValidationParameters(executionInput, document, graphQLSchema, instrumentationState));
623+
InstrumentationContext<List<ValidationError>> validationCtx = nonNullCtx(instrumentation.beginValidation(new InstrumentationValidationParameters(executionInput, document, graphQLSchema, instrumentationState), instrumentationState));
622624
CompletableFuture<List<ValidationError>> cf = new CompletableFuture<>();
623625
validationCtx.onDispatched(cf);
624626

@@ -663,6 +665,9 @@ private static Instrumentation checkInstrumentationDefaultState(Instrumentation
663665
if (instrumentation instanceof DataLoaderDispatcherInstrumentation) {
664666
return instrumentation;
665667
}
668+
if (instrumentation instanceof NoContextChainedInstrumentation) {
669+
return instrumentation;
670+
}
666671
if (instrumentation == null) {
667672
return new DataLoaderDispatcherInstrumentation();
668673
}

‎src/main/java/graphql/collect/ImmutableKit.java‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,31 @@ public static <T, R> ImmutableList<R> map(Collection<? extends T> collection, Fu
8888
return builder.build();
8989
}
9090

91+
/**
92+
* This will map an iterable of items but drop any that are null from the mapped list
93+
*
94+
* This is more efficient than `c.stream().map().collect()` because it does not create the intermediate objects needed
95+
* for the flexible style. Benchmarking has shown this to outperform `stream()`.
96+
*
97+
* @param iterable the iterable to map
98+
* @param mapper the mapper function
99+
* @param <T> for two
100+
* @param <R> for result
101+
*
102+
* @return a map immutable list of results
103+
*/
104+
public static <T, R> ImmutableList<R> mapAndDropNulls(Iterable<? extends T> iterable, Function<? super T, ? extends R> mapper) {
105+
ImmutableList.Builder<R> builder = ImmutableList.builder();
106+
for (T t : iterable) {
107+
R r = mapper.apply(t);
108+
if (r != null) {
109+
builder.add(r);
110+
}
111+
}
112+
return builder.build();
113+
}
114+
115+
91116
/**
92117
* This constructs a new Immutable list from an existing collection and adds a new element to it.
93118
*

‎src/main/java/graphql/execution/AsyncExecutionStrategy.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public CompletableFuture<ExecutionResult> execute(ExecutionContext executionCont
4242
Instrumentation instrumentation = executionContext.getInstrumentation();
4343
InstrumentationExecutionStrategyParameters instrumentationParameters = new InstrumentationExecutionStrategyParameters(executionContext, parameters);
4444

45-
ExecutionStrategyInstrumentationContext executionStrategyCtx = instrumentation.beginExecutionStrategy(instrumentationParameters);
45+
ExecutionStrategyInstrumentationContext executionStrategyCtx = ExecutionStrategyInstrumentationContext.nonNullCtx(instrumentation.beginExecutionStrategy(instrumentationParameters, executionContext.getInstrumentationState()));
4646

4747
MergedSelectionSet fields = parameters.getFields();
4848
Set<String> fieldNames = fields.keySet();

‎src/main/java/graphql/execution/AsyncSerialExecutionStrategy.java‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
import java.util.List;
1111
import java.util.concurrent.CompletableFuture;
1212

13+
import static graphql.execution.instrumentation.SimpleInstrumentationContext.nonNullCtx;
14+
1315
/**
1416
* Async non-blocking execution, but serial: only one field at the time will be resolved.
1517
* See {@link AsyncExecutionStrategy} for a non-serial (parallel) execution of every field.
@@ -31,7 +33,9 @@ public CompletableFuture<ExecutionResult> execute(ExecutionContext executionCont
3133

3234
Instrumentation instrumentation = executionContext.getInstrumentation();
3335
InstrumentationExecutionStrategyParameters instrumentationParameters = new InstrumentationExecutionStrategyParameters(executionContext, parameters);
34-
InstrumentationContext<ExecutionResult> executionStrategyCtx = instrumentation.beginExecutionStrategy(instrumentationParameters);
36+
InstrumentationContext<ExecutionResult> executionStrategyCtx = nonNullCtx(instrumentation.beginExecutionStrategy(instrumentationParameters,
37+
executionContext.getInstrumentationState())
38+
);
3539
MergedSelectionSet fields = parameters.getFields();
3640
ImmutableList<String> fieldNames = ImmutableList.copyOf(fields.keySet());
3741

‎src/main/java/graphql/execution/Execution.java‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import static graphql.execution.ExecutionContextBuilder.newExecutionContextBuilder;
3131
import static graphql.execution.ExecutionStepInfo.newExecutionStepInfo;
3232
import static graphql.execution.ExecutionStrategyParameters.newParameters;
33+
import static graphql.execution.instrumentation.SimpleInstrumentationContext.nonNullCtx;
3334
import static graphql.language.OperationDefinition.Operation.MUTATION;
3435
import static graphql.language.OperationDefinition.Operation.QUERY;
3536
import static graphql.language.OperationDefinition.Operation.SUBSCRIPTION;
@@ -100,15 +101,15 @@ public CompletableFuture<ExecutionResult> execute(Document document, GraphQLSche
100101
InstrumentationExecutionParameters parameters = new InstrumentationExecutionParameters(
101102
executionInput, graphQLSchema, instrumentationState
102103
);
103-
executionContext = instrumentation.instrumentExecutionContext(executionContext, parameters);
104+
executionContext = instrumentation.instrumentExecutionContext(executionContext, parameters, instrumentationState);
104105
return executeOperation(executionContext, executionInput.getRoot(), executionContext.getOperationDefinition());
105106
}
106107

107108

108109
private CompletableFuture<ExecutionResult> executeOperation(ExecutionContext executionContext, Object root, OperationDefinition operationDefinition) {
109110

110111
InstrumentationExecuteOperationParameters instrumentationParams = new InstrumentationExecuteOperationParameters(executionContext);
111-
InstrumentationContext<ExecutionResult> executeOperationCtx = instrumentation.beginExecuteOperation(instrumentationParams);
112+
InstrumentationContext<ExecutionResult> executeOperationCtx = nonNullCtx(instrumentation.beginExecuteOperation(instrumentationParams, executionContext.getInstrumentationState()));
112113

113114
OperationDefinition.Operation operation = operationDefinition.getOperation();
114115
GraphQLObjectType operationRootType;

‎src/main/java/graphql/execution/ExecutionStrategy.java‎

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import static graphql.execution.FieldValueInfo.CompleteValueType.NULL;
6161
import static graphql.execution.FieldValueInfo.CompleteValueType.OBJECT;
6262
import static graphql.execution.FieldValueInfo.CompleteValueType.SCALAR;
63+
import static graphql.execution.instrumentation.SimpleInstrumentationContext.nonNullCtx;
6364
import static graphql.schema.DataFetchingEnvironmentImpl.newDataFetchingEnvironment;
6465
import static graphql.schema.GraphQLTypeUtil.isEnum;
6566
import static graphql.schema.GraphQLTypeUtil.isList;
@@ -203,9 +204,9 @@ protected CompletableFuture<FieldValueInfo> resolveFieldWithInfo(ExecutionContex
203204
Supplier<ExecutionStepInfo> executionStepInfo = FpKit.intraThreadMemoize(() -> createExecutionStepInfo(executionContext, parameters, fieldDef, null));
204205

205206
Instrumentation instrumentation = executionContext.getInstrumentation();
206-
InstrumentationContext<ExecutionResult> fieldCtx = instrumentation.beginField(
207-
new InstrumentationFieldParameters(executionContext, executionStepInfo)
208-
);
207+
InstrumentationContext<ExecutionResult> fieldCtx = nonNullCtx(instrumentation.beginField(
208+
new InstrumentationFieldParameters(executionContext, executionStepInfo), executionContext.getInstrumentationState()
209+
));
209210

210211
CompletableFuture<FetchedValue> fetchFieldFuture = fetchField(executionContext, parameters);
211212
CompletableFuture<FieldValueInfo> result = fetchFieldFuture.thenApply((fetchedValue) ->
@@ -270,10 +271,12 @@ protected CompletableFuture<FetchedValue> fetchField(ExecutionContext executionC
270271
Instrumentation instrumentation = executionContext.getInstrumentation();
271272

272273
InstrumentationFieldFetchParameters instrumentationFieldFetchParams = new InstrumentationFieldFetchParameters(executionContext, environment, parameters, dataFetcher instanceof TrivialDataFetcher);
273-
InstrumentationContext<Object> fetchCtx = instrumentation.beginFieldFetch(instrumentationFieldFetchParams);
274+
InstrumentationContext<Object> fetchCtx = nonNullCtx(instrumentation.beginFieldFetch(instrumentationFieldFetchParams,
275+
executionContext.getInstrumentationState())
276+
);
274277

275278
CompletableFuture<Object> fetchedValue;
276-
dataFetcher = instrumentation.instrumentDataFetcher(dataFetcher, instrumentationFieldFetchParams);
279+
dataFetcher = instrumentation.instrumentDataFetcher(dataFetcher, instrumentationFieldFetchParams, executionContext.getInstrumentationState());
277280
ExecutionId executionId = executionContext.getExecutionId();
278281
try {
279282
Object fetchedValueRaw = dataFetcher.get(environment);
@@ -384,9 +387,9 @@ protected FieldValueInfo completeField(ExecutionContext executionContext, Execut
384387

385388
Instrumentation instrumentation = executionContext.getInstrumentation();
386389
InstrumentationFieldCompleteParameters instrumentationParams = new InstrumentationFieldCompleteParameters(executionContext, parameters, () -> executionStepInfo, fetchedValue);
387-
InstrumentationContext<ExecutionResult> ctxCompleteField = instrumentation.beginFieldComplete(
388-
instrumentationParams
389-
);
390+
InstrumentationContext<ExecutionResult> ctxCompleteField = nonNullCtx(instrumentation.beginFieldComplete(
391+
instrumentationParams, executionContext.getInstrumentationState()
392+
));
390393

391394
NonNullableFieldValidator nonNullableFieldValidator = new NonNullableFieldValidator(executionContext, executionStepInfo);
392395

@@ -518,9 +521,9 @@ protected FieldValueInfo completeValueForList(ExecutionContext executionContext,
518521
InstrumentationFieldCompleteParameters instrumentationParams = new InstrumentationFieldCompleteParameters(executionContext, parameters, () -> executionStepInfo, iterableValues);
519522
Instrumentation instrumentation = executionContext.getInstrumentation();
520523

521-
InstrumentationContext<ExecutionResult> completeListCtx = instrumentation.beginFieldListComplete(
522-
instrumentationParams
523-
);
524+
InstrumentationContext<ExecutionResult> completeListCtx = nonNullCtx(instrumentation.beginFieldListComplete(
525+
instrumentationParams, executionContext.getInstrumentationState()
526+
));
524527

525528
List<FieldValueInfo> fieldValueInfos = new ArrayList<>(size.orElse(1));
526529
int index = 0;

‎src/main/java/graphql/execution/SubscriptionExecutionStrategy.java‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.function.Function;
2121

2222
import static graphql.Assert.assertTrue;
23+
import static graphql.execution.instrumentation.SimpleInstrumentationContext.nonNullCtx;
2324
import static java.util.Collections.singletonMap;
2425

2526
/**
@@ -48,7 +49,10 @@ public CompletableFuture<ExecutionResult> execute(ExecutionContext executionCont
4849

4950
Instrumentation instrumentation = executionContext.getInstrumentation();
5051
InstrumentationExecutionStrategyParameters instrumentationParameters = new InstrumentationExecutionStrategyParameters(executionContext, parameters);
51-
ExecutionStrategyInstrumentationContext executionStrategyCtx = instrumentation.beginExecutionStrategy(instrumentationParameters);
52+
ExecutionStrategyInstrumentationContext executionStrategyCtx = ExecutionStrategyInstrumentationContext.nonNullCtx(instrumentation.beginExecutionStrategy(
53+
instrumentationParameters,
54+
executionContext.getInstrumentationState()
55+
));
5256

5357
CompletableFuture<Publisher<Object>> sourceEventStream = createSourceEventStream(executionContext, parameters);
5458

@@ -123,7 +127,9 @@ private CompletableFuture<ExecutionResult> executeSubscriptionEvent(ExecutionCon
123127
ExecutionStepInfo subscribedFieldStepInfo = createSubscribedFieldStepInfo(executionContext, newParameters);
124128

125129
InstrumentationFieldParameters i13nFieldParameters = new InstrumentationFieldParameters(executionContext, () -> subscribedFieldStepInfo);
126-
InstrumentationContext<ExecutionResult> subscribedFieldCtx = instrumentation.beginSubscribedFieldEvent(i13nFieldParameters);
130+
InstrumentationContext<ExecutionResult> subscribedFieldCtx = nonNullCtx(instrumentation.beginSubscribedFieldEvent(
131+
i13nFieldParameters, executionContext.getInstrumentationState()
132+
));
127133

128134
FetchedValue fetchedValue = unboxPossibleDataFetcherResult(newExecutionContext, parameters, eventPayload);
129135
FieldValueInfo fieldValueInfo = completeField(newExecutionContext, newParameters, fetchedValue);
@@ -139,7 +145,7 @@ private CompletableFuture<ExecutionResult> executeSubscriptionEvent(ExecutionCon
139145
InstrumentationExecutionParameters i13nExecutionParameters = new InstrumentationExecutionParameters(
140146
executionContext.getExecutionInput(), executionContext.getGraphQLSchema(), executionContext.getInstrumentationState());
141147

142-
overallResult = overallResult.thenCompose(executionResult -> instrumentation.instrumentExecutionResult(executionResult, i13nExecutionParameters));
148+
overallResult = overallResult.thenCompose(executionResult -> instrumentation.instrumentExecutionResult(executionResult, i13nExecutionParameters, executionContext.getInstrumentationState()));
143149
return overallResult;
144150
}
145151

0 commit comments

Comments
 (0)