FFFF Fix bug where deferred payloads were not using field aliases by felipe-gdr · Pull Request #3449 · graphql-java/graphql-java · GitHub
[go: up one dir, main page]

Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,15 @@ private Supplier<CompletableFuture<DeferredFragmentCall.FieldWithExecutionResult
DeferredCallContext deferredCallContext
) {
Map<String, MergedField> fields = new LinkedHashMap<>();
fields.put(currentField.getName(), currentField);
fields.put(currentField.getResultKey(), currentField);

ExecutionStrategyParameters callParameters = parameters.transform(builder ->
{
MergedSelectionSet mergedSelectionSet = MergedSelectionSet.newMergedSelectionSet().subFields(fields).build();
builder.deferredCallContext(deferredCallContext)
.field(currentField)
.fields(mergedSelectionSet)
.path(parameters.getPath().segment(currentField.getName()))
.path(parameters.getPath().segment(currentField.getResultKey()))
.parent(null); // this is a break in the parent -> child chain - it's a new start effectively
}
);
Expand All @@ -151,7 +151,7 @@ private Supplier<CompletableFuture<DeferredFragmentCall.FieldWithExecutionResult
instrumentation.beginDeferredField(executionContext.getInstrumentationState());

return dfCache.computeIfAbsent(
currentField.getName(),
currentField.getResultKey(),
// The same field can be associated with multiple defer executions, so
// we memoize the field resolution to avoid multiple calls to the same data fetcher
key -> FpKit.interThreadMemoize(() -> {
Expand All @@ -165,7 +165,7 @@ private Supplier<CompletableFuture<DeferredFragmentCall.FieldWithExecutionResult

return executionResultCF
.thenApply(executionResult ->
new DeferredFragmentCall.FieldWithExecutionResult(currentField.getName(), executionResult)
new DeferredFragmentCall.FieldWithExecutionResult(currentField.getResultKey(), executionResult)
);
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ private DeferPayload transformToDeferredPayload(List<FieldWithExecutionResult> f
ImmutableList.Builder<GraphQLError> errorsBuilder = ImmutableList.builder();

fieldWithExecutionResults.forEach(entry -> {
dataMap.put(entry.fieldName, entry.executionResult.getData());
dataMap.put(entry.resultKey, entry.executionResult.getData());
errorsBuilder.addAll(entry.executionResult.getErrors());
});

Expand All @@ -120,11 +120,11 @@ private DeferPayload transformToDeferredPayload(List<FieldWithExecutionResult> f
}

public static class FieldWithExecutionResult {
private final String fieldName;
private final String resultKey;
private final ExecutionResult executionResult;

public FieldWithExecutionResult(String fieldName, ExecutionResult executionResult) {
this.fieldName = fieldName;
public FieldWithExecutionResult(String resultKey, ExecutionResult executionResult) {
this.resultKey = resultKey;
this.executionResult = executionResult;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class DeferExecutionSupportIntegrationTest extends Specification {
type Query {
post : Post
posts: [Post]
postById(id: ID!): Post
hello: String
item(type: String!): Item
}
Expand Down Expand Up @@ -135,6 +136,9 @@ class DeferExecutionSupportIntegrationTest extends Specification {
[id: "1002"],
[id: "1003"]
]))
.dataFetcher("postById", (env) -> {
return [id: env.getArgument("id")]
})
.dataFetcher("hello", resolve("world"))
.dataFetcher("item", resolveItem())
)
Expand Down Expand Up @@ -201,6 +205,109 @@ class DeferExecutionSupportIntegrationTest extends Specification {
]
}

def "defer with aliased fields"() {
def query = '''
query {
postAlias: post {
idAlias: id
... @defer {
summaryAlias: summary
}
}
}
'''

when:
IncrementalExecutionResult initialResult = executeQuery(query)

then:
initialResult.toSpecification() == [
data : [postAlias: [idAlias: "1001"]],
hasNext: true
]

when:
def incrementalResults = getIncrementalResults(initialResult)

then:
incrementalResults == [
[
hasNext : false,
incremental: [
[
path: ["postAlias"],
data: [summaryAlias: "A summary"]
]
]
]
]
}

def "aliased fields with different parameters"() {
def query = '''
query {
postById(id: "1") {
id
}
... @defer {
post2: postById(id: "2") {
id2: id
}
}
... @defer {
post3: postById(id: "3") {
... @defer {
id3: id
}
}
}
}
'''

when:
IncrementalExecutionResult initialResult = executeQuery(query)

then:
initialResult.toSpecification() == [
data : [postById: [id: "1"]],
hasNext: true
]

when:
def incrementalResults = getIncrementalResults(initialResult)

then:
incrementalResults == [
[
hasNext : true,
incremental: [
[
path: [],
data: [post2: [id2: "2"]]
]
]
],
[
hasNext : true,
incremental: [
[
path: [],
data: [post3: [:]]
]
]
],
[
hasNext : false,
incremental: [
[
path: ["post3"],
data: [id3: "3"]
]
]
]
]
}

def "defer on interface field"() {
def query = """
query {
Expand Down
0