Skip to content

AsynchronousExecutionStrategy without changing the interface of GraphQL#481

Closed
charliechang wants to merge 2 commits intographql-java:masterfrom
charliechang:async_support
Closed

AsynchronousExecutionStrategy without changing the interface of GraphQL#481
charliechang wants to merge 2 commits intographql-java:masterfrom
charliechang:async_support

Conversation

@charliechang
Copy link
Copy Markdown

Here is the PR which implemented the AsynchronousExecutionStrategy by Java 8 CompletableFuture without changing the interface in GraphQL. The returns of GraphQL.getData() will be an instance of CompletionStage<Map>

Please let me know your thought

@bbakerman
Copy link
Copy Markdown
Member

I havent looked that code implementation yet but I think we SHOULD break the API.

It will put is inline with the reference implementation which gives back a Promise aka a CompleteableFuture

I have a PR for that to show it - but its not a true asynch ACTUAL implementation but rather just breaking API shape

@bbakerman
Copy link
Copy Markdown
Member

This is the PR in question

#380

I think strongly that we should have a Promise based return value before we add an actual asynch execution strategy

Copy link
Copy Markdown
Member

@bbakerman bbakerman left a comment

Choose a reason for hiding this comment

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

I think this is a great PR.

In fact it begs the question that if we adopted this, that the base SimpleExecutionStrategy becomes this with .join() as the behavior say.

I do think that we should get the other Promise PR in place before adding this however

ExecutionParameters parameters) throws NonNullableFieldWasNullException {

Map<String, List<Field>> fields = parameters.fields();
Map<String,Object> results = Collections.synchronizedMap(new HashMap<>());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ConcurrentHashMap is a better choice than synchronizedMap


}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Mostly pondering here.

I wonder if we should make the complete value list truly async. Should it join back as one result at this point?

Is there any disadvantage is leaving it purely async for many items in a list? Is there any expectation that is this point you have resolved the value so it can be sent onto future calls?

import graphql.execution.instrumentation.InstrumentationContext;
import graphql.execution.instrumentation.parameters.FieldFetchParameters;
import graphql.execution.instrumentation.parameters.FieldParameters;
import graphql.language.Field;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we dont do * imports. Full imports please

handleDataFetchingException(executionContext, fieldDef, argumentValues, new ExecutionException(th));
fetchCtx.onEnd(th);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The Instrumentation is not called back here and hence is lost

        fetchCtx.onEnd(resolvedValue);
  • Add in intrumentation call

import static graphql.execution.FieldCollectorParameters.newParameters;
import static graphql.execution.TypeInfo.newTypeInfo;

public class AsynchronousExecutionStrategy extends ExecutionStrategy {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This comment is an aside to this PR btw.

@andimarek

There is a lot of repeated code in here from the base ExecutionStrategy. Perhaps we should make a ExecutionStrategyHelper and use composition instead of inheritance to allow better reuse??

Hard problem I know

Object result = parameters.source();
GraphQLType fieldType = parameters.typeInfo().type();

if (result == null) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

fyi - there are a few PRS in the pipe that will make this code break. But thats often always the case

then:
assert result == expected
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Are we trying to say that the first things to be resolved (grand) is likely to be the last thing to be completed (50ms) and hence it come back in the right order.?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just trying to work out what the tests really proves

@andimarek
Copy link
Copy Markdown
Member

@charliechang Please have a look at #380 for a first start.

@andimarek
Copy link
Copy Markdown
Member

closing it, because we decided to make ExecutionStrategy itself async and we already merged a first step in this direction: #380.

@charliechang thanks a lot for this PR and the work you have put into it!

@andimarek andimarek closed this Jul 5, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants