Skip to content
Closed
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
11 changes: 10 additions & 1 deletion src/main/java/graphql/GraphQL.java
Original file line number Diff line number Diff line change
Expand Up @@ -513,15 +513,24 @@ public CompletableFuture<ExecutionResult> executeAsync(ExecutionInput executionI
InstrumentationExecutionParameters inputInstrumentationParameters = new InstrumentationExecutionParameters(executionInput, this.graphQLSchema, instrumentationState);
executionInput = instrumentation.instrumentExecutionInput(executionInput, inputInstrumentationParameters);

CompletableFuture<ExecutionResult> beginExecutionCF = new CompletableFuture<>();
InstrumentationExecutionParameters instrumentationParameters = new InstrumentationExecutionParameters(executionInput, this.graphQLSchema, instrumentationState);
InstrumentationContext<ExecutionResult> executionInstrumentation = instrumentation.beginExecution(instrumentationParameters);
executionInstrumentation.onDispatched(beginExecutionCF);

GraphQLSchema graphQLSchema = instrumentation.instrumentSchema(this.graphQLSchema, instrumentationParameters);

CompletableFuture<ExecutionResult> executionResult = parseValidateAndExecute(executionInput, graphQLSchema, instrumentationState);
//
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this fix - it is indeed missing. But its slightly wrong in this fix

Tthis should be before the method parseValidateAndExecute

The idea of onDispacthed is indicate that an instrumented stage is now really underway with a CF promise to it being completed.

With a sync process like this it should be immediately after its called. That is its dispatched immediately. Near zero nanos later.

It should be this

    public CompletableFuture<ExecutionResult> executeAsync(ExecutionInput executionInput) {
        try {
            if (logNotSafe.isDebugEnabled()) {
                logNotSafe.debug("Executing request. operation name: '{}'. query: '{}'. variables '{}'", executionInput.getOperationName(), executionInput.getQuery(), executionInput.getVariables());
            }
            executionInput = ensureInputHasId(executionInput);

            InstrumentationState instrumentationState = instrumentation.createState(new InstrumentationCreateStateParameters(this.graphQLSchema, executionInput));

            InstrumentationExecutionParameters inputInstrumentationParameters = new InstrumentationExecutionParameters(executionInput, this.graphQLSchema, instrumentationState);
            executionInput = instrumentation.instrumentExecutionInput(executionInput, inputInstrumentationParameters);


            CompletableFuture<ExecutionResult> beginExecutionCF = new CompletableFuture<>();
            InstrumentationExecutionParameters instrumentationParameters = new InstrumentationExecutionParameters(executionInput, this.graphQLSchema, instrumentationState);
            InstrumentationContext<ExecutionResult> executionInstrumentation = instrumentation.beginExecution(instrumentationParameters);
            executionInstrumentation.onDispatched(beginExecutionCF);

            GraphQLSchema graphQLSchema = instrumentation.instrumentSchema(this.graphQLSchema, instrumentationParameters);

            CompletableFuture<ExecutionResult> executionResult = parseValidateAndExecute(executionInput, graphQLSchema, instrumentationState);
            //
            // finish up instrumentation
            executionResult = executionResult.whenComplete(executionInstrumentation::onCompleted);
            //
            // allow instrumentation to tweak the result
            executionResult = executionResult.thenCompose(result -> instrumentation.instrumentExecutionResult(result, instrumentationParameters));
            executionResult = executionResult.whenComplete((result,throwable) -> {
                if (throwable != null) {
                    beginExecutionCF.completeExceptionally(throwable);
                } else {
                    beginExecutionCF.complete(result);
                }
                executionInstrumentation.onDispatched(beginExecutionCF);
            });
            return executionResult;
        } catch (AbortExecutionException abortException) {
            return CompletableFuture.completedFuture(abortException.toExecutionResult());
        }

That is its dispatched IMMEDIATELY and the CF given on that is completed at the end

Can you change your PR and take this code please. This is the right fix

this will change the test below

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome. I'll make the change. Thank you for the quick turn around.

Copy link
Author

@bsara bsara Feb 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't seem to get the tests to run locally for me (something with the gradle daemon). Could I get approval for this to run the tests? I don't want to move this from draft status until I can successfully test it, of course.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to run the tests inside IDEA - albeit .gradlew clean build also works for me

I have approved the build and hence the github actions will run the builds

// finish up instrumentation
executionResult = executionResult.whenComplete(executionInstrumentation::onCompleted);
executionResult = executionResult.whenComplete((result, throwable) -> {
if (throwable != null) {
beginExecutionCF.completeExceptionally(throwable);
} else {
beginExecutionCF.complete(result);
}
executionInstrumentation.onCompleted(result, throwable);
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah that is better than what I proposed

//
// allow instrumentation to tweak the result
executionResult = executionResult.thenCompose(result -> instrumentation.instrumentExecutionResult(result, instrumentationParameters));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,29 +42,41 @@ class InstrumentationTest extends Specification {

def expected = [
"start:execution",
"onDispatched:execution",

"start:parse",
"onDispatched:parse",
"end:parse",

"start:validation",
"onDispatched:validation",
"end:validation",

"start:execute-operation",
"onDispatched:execute-operation",

"start:execution-strategy",
"onDispatched:execution-strategy",

"start:field-hero",
"onDispatched:field-hero",
"start:fetch-hero",
"onDispatched:fetch-hero",
"end:fetch-hero",

"start:complete-hero",
"onDispatched:complete-hero",

"start:execution-strategy",
"onDispatched:execution-strategy",

"start:field-id",
"onDispatched:field-id",
"start:fetch-id",
"onDispatched:fetch-id",
"end:fetch-id",
"start:complete-id",
"onDispatched:complete-id",
"end:complete-id",
"end:field-id",

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class TestingInstrumentContext<T> implements InstrumentationContext<T> {

@Override
void onDispatched(CompletableFuture<T> result) {
this.executionList << "onDispatched:$op"
}

@Override
Expand Down