Skip to content

Commit 2c9187e

Browse files
authored
Merge pull request #166 from graph-quilt/handle-entitykey-with-alias
Support Federated Queries with Aliased Keys
2 parents 7b27634 + 1e5b5d3 commit 2c9187e

File tree

8 files changed

+562
-48
lines changed

8 files changed

+562
-48
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
<awssdk2.version>2.7.2</awssdk2.version>
3939
<graphql-sdl-version>3.0.1</graphql-sdl-version>
4040
<xtextVersion>2.26.0</xtextVersion>
41-
<graphQLVersion>17.4</graphQLVersion>
41+
<graphQLVersion>17.5</graphQLVersion>
4242
</properties>
4343

4444
<profiles>

src/main/java/com/intuit/graphql/orchestrator/batch/EntityFetcherBatchLoader.java

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
import com.intuit.graphql.orchestrator.federation.metadata.FederationMetadata;
1313
import com.intuit.graphql.orchestrator.federation.metadata.KeyDirectiveMetadata;
1414
import com.intuit.graphql.orchestrator.schema.ServiceMetadata;
15+
import com.intuit.graphql.orchestrator.utils.SelectionCollector;
1516
import graphql.GraphQLContext;
1617
import graphql.execution.DataFetcherResult;
18+
import graphql.execution.MergedField;
1719
import graphql.introspection.Introspection;
1820
import graphql.language.Field;
1921
import graphql.language.InlineFragment;
@@ -27,6 +29,7 @@
2729
import java.util.HashMap;
2830
import java.util.List;
2931
import java.util.Map;
32+
import java.util.Objects;
3033
import java.util.concurrent.CompletionStage;
3134
import java.util.stream.Collectors;
3235
import org.apache.commons.collections4.CollectionUtils;
@@ -58,8 +61,7 @@ public CompletionStage<List<DataFetcherResult<Object>>> load(List<DataFetchingEn
5861
GraphQLContext graphQLContext = dfeTemplate.getContext();
5962

6063
List<Map<String, Object>> representations = dataFetchingEnvironments.stream()
61-
.map(DataFetchingEnvironment::getSource)
62-
.map(source -> createRepresentation((Map<String, Object>) source))
64+
.map(this::createRepresentation)
6365
.collect(Collectors.toList());
6466

6567
List<InlineFragment> inlineFragments = new ArrayList<>();
@@ -96,6 +98,7 @@ private List<String> generateRepresentationTemplate(FederationMetadata.EntityExt
9698
.build();
9799
}
98100

101+
99102
if(CollectionUtils.isNotEmpty(metadata.getRequiredFields(fieldName))) {
100103
metadata.getRequiredFields(fieldName)
101104
.stream()
@@ -133,20 +136,44 @@ private InlineFragment createEntityRequestInlineFragment(DataFetchingEnvironment
133136
newField()
134137
.selectionSet(fieldSelectionSet)
135138
.name(originalField.getName())
139+
.alias(originalField.getAlias())
136140
.build())
137141
.build());
138142
return inlineFragmentBuilder.build();
139143
}
140144

141145
private Map<String, Object> createRepresentation(
142-
Map<String, Object> dataSource
146+
DataFetchingEnvironment dataFetchingEnvironment
143147
){
148+
Map<String, Object> dataSource = dataFetchingEnvironment.getSource();
149+
Map<String, String> keyToAliasMap = buildkeyToAliasMap(dataFetchingEnvironment);
150+
144151
Map<String, Object> entityRepresentation = new HashMap<>();
145152
entityRepresentation.put(Introspection.TypeNameMetaFieldDef.getName(), this.entityTypeName);
146153

147154
this.representationFieldTemplate
148-
.forEach(fieldName -> entityRepresentation.put(fieldName, dataSource.get(fieldName)));
155+
.forEach(fieldName -> {
156+
String keyAlias = keyToAliasMap.get(fieldName);
157+
String dataSourceKey = keyAlias != null ? keyAlias : fieldName;
158+
Object value = Objects.requireNonNull(dataSource.get(dataSourceKey), "Entity Fetch failed. Key " + dataSourceKey + " not found in source");
159+
entityRepresentation.put(fieldName, value);
160+
});
149161

150162
return entityRepresentation;
151163
}
164+
165+
/**
166+
* builds mapping of fieldName-alias. If fieldName has no alias, it will be mapped to itself.
167+
*/
168+
private Map<String, String> buildkeyToAliasMap(DataFetchingEnvironment dataFetchingEnvironment) {
169+
MergedField parentField = dataFetchingEnvironment.getExecutionStepInfo().getParent().getField();
170+
171+
SelectionCollector selectionCollector = new SelectionCollector(dataFetchingEnvironment.getFragmentsByName());
172+
return selectionCollector.collectFields(parentField.getSingleField().getSelectionSet())
173+
.values()
174+
.stream()
175+
.filter(field -> this.representationFieldTemplate.contains(field.getName()))
176+
.collect(Collectors.toMap(Field::getName, field -> field.getAlias() == null? field.getName() : field.getAlias()));
177+
}
178+
152179
}

src/main/java/com/intuit/graphql/orchestrator/batch/EntityFetcherBatchResultTransformer.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.intuit.graphql.orchestrator.federation.EntityFetchingException;
44
import graphql.GraphQLError;
55
import graphql.execution.DataFetcherResult;
6+
import graphql.language.Field;
67
import graphql.schema.DataFetchingEnvironment;
78
import lombok.extern.slf4j.Slf4j;
89
import org.apache.commons.collections4.CollectionUtils;
@@ -54,8 +55,13 @@ public List<DataFetcherResult<Object>> toBatchResult(DataFetcherResult<Map<Strin
5455

5556
//using IntStream instead of regular for loop or atomic reference, so we can parallelize this if we want
5657
IntStream.range(0, _entities.size()).forEach( idx -> {
58+
59+
DataFetchingEnvironment dataFetchingEnvironment = dataFetchingEnvironments.get(idx);
60+
Field field = dataFetchingEnvironment.getField();
61+
String fieldNameOrAlias = field.getAlias() == null ? field.getName() : field.getAlias();
62+
5763
Map<String, Object> entityInfo = _entities.get(idx);
58-
Object fieldData = (entityInfo != null) ? entityInfo.get(this.extFieldName) : null;
64+
Object fieldData = (entityInfo != null) ? entityInfo.get(fieldNameOrAlias) : null;
5965
List<GraphQLError> graphQLErrors = (List<GraphQLError>) entityInfo.getOrDefault("errors", new ArrayList<>());
6066

6167
dataFetcherResults.add(DataFetcherResult.newResult()

0 commit comments

Comments
 (0)