From 42528b7903f70d41287b2c7608711d1dc247127b Mon Sep 17 00:00:00 2001 From: bshah6 Date: Tue, 31 May 2022 17:45:03 -0700 Subject: [PATCH 1/2] optimize service metadata implementation --- .../metadata/FederationMetadata.java | 46 +++--- .../schema/ServiceMetadataImpl.java | 140 ++++++++++++++++++ .../schema/fold/XtextGraphFolder.java | 65 ++++---- .../schema/transform/AllTypesTransformer.java | 60 ++++---- .../FederationTransformerPreMerge.java | 2 +- .../orchestrator/stitching/XtextStitcher.java | 51 +++++-- .../orchestrator/xtext/XtextGraph.java | 68 +-------- src/test/groovy/helpers/SchemaTestUtil.groovy | 2 +- .../batch/GraphQLServiceBatchLoaderTest.java | 8 +- .../datafetcher/RestDataFetcherTest.java | 4 +- ...FieldResolverTransformerPostMergeTest.java | 2 +- .../FieldResolverTransformerPreMergeTest.java | 32 ++-- 12 files changed, 300 insertions(+), 180 deletions(-) create mode 100644 src/main/java/com/intuit/graphql/orchestrator/schema/ServiceMetadataImpl.java diff --git a/src/main/java/com/intuit/graphql/orchestrator/federation/metadata/FederationMetadata.java b/src/main/java/com/intuit/graphql/orchestrator/federation/metadata/FederationMetadata.java index 39d166ff..95004d81 100644 --- a/src/main/java/com/intuit/graphql/orchestrator/federation/metadata/FederationMetadata.java +++ b/src/main/java/com/intuit/graphql/orchestrator/federation/metadata/FederationMetadata.java @@ -5,7 +5,6 @@ import com.intuit.graphql.graphQL.FieldDefinition; import com.intuit.graphql.graphQL.TypeDefinition; import com.intuit.graphql.orchestrator.ServiceProvider; -import com.intuit.graphql.orchestrator.schema.ServiceMetadata; import graphql.language.Field; import graphql.schema.FieldCoordinates; import java.util.HashMap; @@ -25,19 +24,23 @@ @Getter public class FederationMetadata { - private final ServiceMetadata serviceMetadata; + private final ServiceProvider serviceProvider; - /** entities owned by the service */ + /** + * entities owned by the service + */ private final Map entitiesByTypename = new HashMap<>(); - /** entities extended by the service */ + /** + * entities extended by the service + */ private final Map extensionsByTypename = new HashMap<>(); private final Map> requiresFieldSetByCoordinate = new HashMap<>(); - public FederationMetadata(ServiceMetadata serviceMetadata) { - Objects.requireNonNull(serviceMetadata); - this.serviceMetadata = serviceMetadata; + public FederationMetadata(ServiceProvider serviceProvider) { + Objects.requireNonNull(serviceProvider); + this.serviceProvider = serviceProvider; } public boolean isFieldExternal(FieldCoordinates fieldCoordinates) { @@ -72,10 +75,15 @@ public Set getRequireFields(FieldCoordinates fieldCoordinates) { @Builder @Getter public static class EntityMetadata { - @NonNull private final String typeName; - @NonNull private final List keyDirectives; - @NonNull private final Set fields; - @NonNull private final FederationMetadata federationMetadata; + + @NonNull + private final String typeName; + @NonNull + private final List keyDirectives; + @NonNull + private final Set fields; + @NonNull + private final FederationMetadata federationMetadata; public static Set getFieldsFrom(TypeDefinition entityDefinition) { Set output = new HashSet<>(); // make sure HashSet is used @@ -89,10 +97,15 @@ public static Set getFieldsFrom(TypeDefinition entityDefinition) { @Builder @Getter public static class EntityExtensionMetadata { - @NonNull private final String typeName; - @NonNull private final List keyDirectives; - @NonNull private final Map> requiredFieldsByFieldName; - @NonNull private final FederationMetadata federationMetadata; + + @NonNull + private final String typeName; + @NonNull + private final List keyDirectives; + @NonNull + private final Map> requiredFieldsByFieldName; + @NonNull + private final FederationMetadata federationMetadata; // TODO @provides private EntityMetadata baseEntityMetadata; @@ -112,13 +125,12 @@ public void setBaseEntityMetadata(EntityMetadata baseEntityMetadata) { } public ServiceProvider getServiceProvider() { - return this.federationMetadata.getServiceMetadata().getServiceProvider(); + return this.federationMetadata.getServiceProvider(); } public ServiceProvider getBaseServiceProvider() { return this.baseEntityMetadata .getFederationMetadata() - .getServiceMetadata() .getServiceProvider(); } diff --git a/src/main/java/com/intuit/graphql/orchestrator/schema/ServiceMetadataImpl.java b/src/main/java/com/intuit/graphql/orchestrator/schema/ServiceMetadataImpl.java new file mode 100644 index 00000000..9e39365a --- /dev/null +++ b/src/main/java/com/intuit/graphql/orchestrator/schema/ServiceMetadataImpl.java @@ -0,0 +1,140 @@ +package com.intuit.graphql.orchestrator.schema; + +import static java.util.Objects.requireNonNull; + +import com.intuit.graphql.orchestrator.ServiceProvider; +import com.intuit.graphql.orchestrator.federation.metadata.FederationMetadata; +import com.intuit.graphql.orchestrator.schema.transform.FieldResolverContext; +import graphql.schema.FieldCoordinates; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import lombok.Getter; + +@Getter +public class ServiceMetadataImpl implements ServiceMetadata { + + private final Map typeMetadataMap; + private final ServiceProvider serviceProvider; + private final FederationMetadata federationMetadata; + private final boolean hasInterfaceOrUnion; + private final boolean hasFieldResolverDefinition; + + private ServiceMetadataImpl(Builder builder) { + typeMetadataMap = builder.typeMetadataMap; + serviceProvider = requireNonNull(builder.serviceProvider); + federationMetadata = builder.federationMetadata; + hasInterfaceOrUnion = builder.hasInterfaceOrUnion; + hasFieldResolverDefinition = builder.hasFieldResolverDefinition; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public static Builder newBuilder(ServiceMetadataImpl copy) { + Builder builder = new Builder(); + builder.typeMetadataMap = copy.getTypeMetadataMap(); + builder.serviceProvider = copy.getServiceProvider(); + builder.federationMetadata = copy.getFederationMetadata(); + builder.hasInterfaceOrUnion = copy.isHasInterfaceOrUnion(); + builder.hasFieldResolverDefinition = copy.isHasFieldResolverDefinition(); + return builder; + } + + @Override + public boolean hasType(String typeName) { + return this.typeMetadataMap.containsKey(typeName); + } + + @Override + public boolean requiresTypenameInjection() { + return this.hasInterfaceOrUnion; + } + + @Override + public boolean hasFieldResolverDirective() { + return this.hasFieldResolverDefinition; + } + + @Override + public boolean isFederationService() { + return this.serviceProvider.isFederationProvider(); + } + + @Override + public boolean shouldRemoveExternalFields() { + return this.hasFieldResolverDirective() || this.isFederationService(); + } + + + @Override + public ServiceProvider getServiceProvider() { + return this.serviceProvider; + } + + @Override + public FieldResolverContext getFieldResolverContext(FieldCoordinates fieldCoordinates) { + return Optional.ofNullable(this.typeMetadataMap.get(fieldCoordinates.getTypeName())) + .map(typeMetadata -> typeMetadata.getFieldResolverContext(fieldCoordinates.getFieldName())) + .orElse(null); + } + + @Override + public boolean isOwnedByEntityExtension(FieldCoordinates fieldCoordinates) { + return this.serviceProvider.isFederationProvider() && federationMetadata.isFieldExternal(fieldCoordinates); + } + + + @Override + public boolean isEntity(String typename) { + return this.isFederationService() && this.federationMetadata.isEntity(typename); + } + + @Override + public FederationMetadata getFederationServiceMetadata() { + return federationMetadata; + } + + + public static final class Builder { + + private Map typeMetadataMap = new HashMap<>(); + private ServiceProvider serviceProvider; + private FederationMetadata federationMetadata; + private boolean hasInterfaceOrUnion; + private boolean hasFieldResolverDefinition; + + private Builder() { + } + + public Builder typeMetadataMap(Map val) { + typeMetadataMap = val; + return this; + } + + public Builder serviceProvider(ServiceProvider val) { + serviceProvider = val; + return this; + } + + public Builder federationMetadata(FederationMetadata val) { + federationMetadata = val; + return this; + } + + public Builder hasInterfaceOrUnion(boolean val) { + hasInterfaceOrUnion = val; + return this; + } + + public Builder hasFieldResolverDefinition(boolean val) { + hasFieldResolverDefinition = val; + return this; + } + + public ServiceMetadataImpl build() { + return new ServiceMetadataImpl(this); + } + } +} diff --git a/src/main/java/com/intuit/graphql/orchestrator/schema/fold/XtextGraphFolder.java b/src/main/java/com/intuit/graphql/orchestrator/schema/fold/XtextGraphFolder.java index d1d9d1fd..7d2b0d57 100644 --- a/src/main/java/com/intuit/graphql/orchestrator/schema/fold/XtextGraphFolder.java +++ b/src/main/java/com/intuit/graphql/orchestrator/schema/fold/XtextGraphFolder.java @@ -1,5 +1,11 @@ package com.intuit.graphql.orchestrator.schema.fold; +import static com.intuit.graphql.orchestrator.schema.fold.FieldMergeValidations.checkMergeEligibility; +import static com.intuit.graphql.orchestrator.utils.DescriptionUtils.mergeDescriptions; +import static com.intuit.graphql.orchestrator.xtext.DataFetcherContext.STATIC_DATAFETCHER_CONTEXT; +import static com.intuit.graphql.orchestrator.xtext.GraphQLFactoryDelegate.createObjectType; +import static com.intuit.graphql.utils.XtextTypeUtils.unwrapAll; + import com.intuit.graphql.graphQL.EnumTypeDefinition; import com.intuit.graphql.graphQL.EnumValueDefinition; import com.intuit.graphql.graphQL.FieldDefinition; @@ -19,9 +25,6 @@ import com.intuit.graphql.orchestrator.xtext.FieldContext; import com.intuit.graphql.orchestrator.xtext.XtextGraph; import com.intuit.graphql.utils.XtextTypeUtils; -import org.eclipse.emf.common.util.EList; -import org.eclipse.emf.ecore.util.EcoreUtil; - import java.util.Collection; import java.util.EnumMap; import java.util.HashMap; @@ -30,12 +33,8 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; - -import static com.intuit.graphql.orchestrator.schema.fold.FieldMergeValidations.checkMergeEligibility; -import static com.intuit.graphql.orchestrator.utils.DescriptionUtils.mergeDescriptions; -import static com.intuit.graphql.orchestrator.xtext.DataFetcherContext.STATIC_DATAFETCHER_CONTEXT; -import static com.intuit.graphql.orchestrator.xtext.GraphQLFactoryDelegate.createObjectType; -import static com.intuit.graphql.utils.XtextTypeUtils.unwrapAll; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.util.EcoreUtil; public class XtextGraphFolder implements Foldable { @@ -69,18 +68,21 @@ private XtextGraph merge(XtextGraph accumulator, XtextGraph current) { merge(accumulator.getOperationType(op), current.getOperationType(op), current.getServiceProvider())); } - if(current.isFederationService()) { + if (current.getServiceProvider().isFederationProvider()) { current.getValueTypesByName().values() - .forEach(incomingSharedType -> { - TypeDefinition preexistingTypeDefinition = accumulator.getType(incomingSharedType.getName()); - if(incomingSharedType instanceof EnumTypeDefinition) { - mergeSharedValueType((EnumTypeDefinition) preexistingTypeDefinition, (EnumTypeDefinition) incomingSharedType, current.getServiceProvider()); - } else if(incomingSharedType instanceof ObjectTypeDefinition) { - mergeSharedValueType((ObjectTypeDefinition) preexistingTypeDefinition, (ObjectTypeDefinition) incomingSharedType, current.getServiceProvider()); - } else if(incomingSharedType instanceof InterfaceTypeDefinition) { - mergeSharedValueType((InterfaceTypeDefinition) preexistingTypeDefinition, (InterfaceTypeDefinition) incomingSharedType, current.getServiceProvider()); - } - }); + .forEach(incomingSharedType -> { + TypeDefinition preexistingTypeDefinition = accumulator.getType(incomingSharedType.getName()); + if (incomingSharedType instanceof EnumTypeDefinition) { + mergeSharedValueType((EnumTypeDefinition) preexistingTypeDefinition, + (EnumTypeDefinition) incomingSharedType, current.getServiceProvider()); + } else if (incomingSharedType instanceof ObjectTypeDefinition) { + mergeSharedValueType((ObjectTypeDefinition) preexistingTypeDefinition, + (ObjectTypeDefinition) incomingSharedType, current.getServiceProvider()); + } else if (incomingSharedType instanceof InterfaceTypeDefinition) { + mergeSharedValueType((InterfaceTypeDefinition) preexistingTypeDefinition, + (InterfaceTypeDefinition) incomingSharedType, current.getServiceProvider()); + } + }); } resolveTypeConflicts(accumulator.getTypes(), current.getTypes(), current); @@ -118,7 +120,8 @@ private void resolveTypeConflicts(final Map existing, TypeDefinition existingType = existing.get(typeName); if (Objects.nonNull(existingType) && !nestedTypes.containsKey(existingType.getName())) { TypeDefinition conflictingType = current.get(typeName); - XtextTypeConflictResolver.INSTANCE.resolve(conflictingType, existingType, currentGraph.getServiceProvider().isFederationProvider()); + XtextTypeConflictResolver.INSTANCE + .resolve(conflictingType, existingType, currentGraph.getServiceProvider().isFederationProvider()); } } } @@ -170,7 +173,7 @@ private ObjectTypeDefinition merge(ObjectTypeDefinition current, ObjectTypeDefin * @return merged object */ private TypeDefinition mergeSharedValueType(EnumTypeDefinition current, EnumTypeDefinition newComer, - ServiceProvider newComerServiceProvider) { + ServiceProvider newComerServiceProvider) { //nothing to merge if (current == null || !newComerServiceProvider.isFederationProvider()) { return current; @@ -194,15 +197,15 @@ private TypeDefinition mergeSharedValueType(EnumTypeDefinition current, EnumType } private TypeDefinition mergeSharedValueType(ObjectTypeDefinition current, ObjectTypeDefinition newComer, - ServiceProvider newComerServiceProvider) { + ServiceProvider newComerServiceProvider) { if (current == null || !newComerServiceProvider.isFederationProvider()) { return current; } newComer.getFieldDefinition().forEach(newField -> { Optional currentField = current.getFieldDefinition().stream() - .filter(fieldName -> newField.getName().equals(fieldName.getName())) - .findFirst(); + .filter(fieldName -> newField.getName().equals(fieldName.getName())) + .findFirst(); if (!currentField.isPresent()) { addNewFieldToObject(current, newField, newComerServiceProvider); @@ -217,15 +220,15 @@ private TypeDefinition mergeSharedValueType(ObjectTypeDefinition current, Object } private TypeDefinition mergeSharedValueType(InterfaceTypeDefinition current, InterfaceTypeDefinition newComer, - ServiceProvider newComerServiceProvider) { + ServiceProvider newComerServiceProvider) { if (current == null || !newComerServiceProvider.isFederationProvider()) { return current; } newComer.getFieldDefinition().forEach(newField -> { Optional currentField = current.getFieldDefinition().stream() - .filter(fieldName -> newField.getName().equals(fieldName.getName())) - .findFirst(); + .filter(fieldName -> newField.getName().equals(fieldName.getName())) + .findFirst(); if (!currentField.isPresent()) { addNewFieldToObject(current, newField, newComerServiceProvider); @@ -281,13 +284,13 @@ private void addNewFieldToObject(ObjectTypeDefinition objectTypeDefinition, Fiel private void addNewFieldToObject(EnumTypeDefinition enumTypeDefinition, EnumValueDefinition valueDefinition, - ServiceProvider serviceProvider) { + ServiceProvider serviceProvider) { addFieldContextToRegistry(enumTypeDefinition.getName(), valueDefinition.getEnumValue(), serviceProvider); enumTypeDefinition.getEnumValueDefinition().add(EcoreUtil.copy(valueDefinition)); } private void addNewFieldToObject(InterfaceTypeDefinition interfaceTypeDefinition, FieldDefinition fieldDefinition, - ServiceProvider serviceProvider) { + ServiceProvider serviceProvider) { addFieldContextToRegistry(interfaceTypeDefinition.getName(), fieldDefinition.getName(), serviceProvider); interfaceTypeDefinition.getFieldDefinition().add(EcoreUtil.copy(fieldDefinition)); } @@ -297,7 +300,7 @@ private void addFieldContextToRegistry(String parentName, String definitionName, final FieldContext fieldContext = new FieldContext(parentName, definitionName); accCodeRegistry.put(fieldContext, DataFetcherContext.newBuilder().namespace(serviceProvider.getNameSpace()) - .serviceType(serviceProvider.getSeviceType()).build()); + .serviceType(serviceProvider.getSeviceType()).build()); } /** diff --git a/src/main/java/com/intuit/graphql/orchestrator/schema/transform/AllTypesTransformer.java b/src/main/java/com/intuit/graphql/orchestrator/schema/transform/AllTypesTransformer.java index 1ab6754c..2afa29da 100644 --- a/src/main/java/com/intuit/graphql/orchestrator/schema/transform/AllTypesTransformer.java +++ b/src/main/java/com/intuit/graphql/orchestrator/schema/transform/AllTypesTransformer.java @@ -2,9 +2,7 @@ import static com.intuit.graphql.orchestrator.utils.FederationConstants.FEDERATION_EXTENDS_DIRECTIVE; import static com.intuit.graphql.orchestrator.utils.FederationConstants.FEDERATION_KEY_DIRECTIVE; -import static com.intuit.graphql.orchestrator.utils.FederationUtils.isBaseType; import static com.intuit.graphql.orchestrator.utils.FederationUtils.isTypeSystemForBaseType; -import static com.intuit.graphql.orchestrator.utils.FederationUtils.isTypeSystemForExtensionType; import static com.intuit.graphql.orchestrator.utils.XtextTypeUtils.toDescriptiveString; import static com.intuit.graphql.orchestrator.utils.XtextUtils.definitionContainsDirective; import static com.intuit.graphql.orchestrator.utils.XtextUtils.getAllTypes; @@ -25,18 +23,15 @@ import com.intuit.graphql.orchestrator.utils.FederationUtils; import com.intuit.graphql.orchestrator.xtext.XtextGraph; import java.util.HashMap; - import java.util.Map; import java.util.Objects; import java.util.function.Function; import java.util.stream.Collectors; - import org.apache.commons.collections4.CollectionUtils; public class AllTypesTransformer implements Transformer { - @Override public XtextGraph transform(XtextGraph source) { Map types = getAllTypes(source.getXtextResourceSet()) @@ -50,53 +45,58 @@ public XtextGraph transform(XtextGraph source) { })); updateDescWithNamespace(types, source.getServiceProvider().getNameSpace()); - if(source.isFederationService()) { + if (source.getServiceProvider().isFederationProvider()) { Map baseEntities = getAllTypes(source.getXtextResourceSet()) - .filter(typeDefinition -> definitionContainsDirective(typeDefinition, FEDERATION_KEY_DIRECTIVE)) - .filter(FederationUtils::isBaseType) - .collect(Collectors.toMap(TypeDefinition::getName, Function.identity())); + .filter(typeDefinition -> definitionContainsDirective(typeDefinition, FEDERATION_KEY_DIRECTIVE)) + .filter(FederationUtils::isBaseType) + .collect(Collectors.toMap(TypeDefinition::getName, Function.identity())); - Map extensionEntities = Streams.concat( + Map extensionEntities = Streams.concat( getTypeSystemDefinition(source.getXtextResourceSet()) - .filter(FederationUtils::isTypeSystemForBaseType) - .filter(typeSystemDefinition -> definitionContainsDirective(typeSystemDefinition.getType(), FEDERATION_KEY_DIRECTIVE)) - .filter(typeSystemDefinition -> definitionContainsDirective(typeSystemDefinition.getType(), FEDERATION_EXTENDS_DIRECTIVE)), + .filter(FederationUtils::isTypeSystemForBaseType) + .filter(typeSystemDefinition -> definitionContainsDirective(typeSystemDefinition.getType(), + FEDERATION_KEY_DIRECTIVE)) + .filter(typeSystemDefinition -> definitionContainsDirective(typeSystemDefinition.getType(), + FEDERATION_EXTENDS_DIRECTIVE)), getTypeSystemDefinition(source.getXtextResourceSet()) - .filter(FederationUtils::isTypeSystemForExtensionType) - .filter(typeSystemDefinition -> typeSystemDefinition.getTypeExtension() instanceof ObjectTypeExtensionDefinition || typeSystemDefinition.getTypeExtension() instanceof InterfaceTypeExtensionDefinition) - .filter(typeSystemDefinition -> definitionContainsDirective(typeSystemDefinition.getTypeExtension(), FEDERATION_KEY_DIRECTIVE)) + .filter(FederationUtils::isTypeSystemForExtensionType) + .filter(typeSystemDefinition -> + typeSystemDefinition.getTypeExtension() instanceof ObjectTypeExtensionDefinition + || typeSystemDefinition.getTypeExtension() instanceof InterfaceTypeExtensionDefinition) + .filter(typeSystemDefinition -> definitionContainsDirective(typeSystemDefinition.getTypeExtension(), + FEDERATION_KEY_DIRECTIVE)) ).collect(Collectors.toMap( - (typeSystemDefinition -> isTypeSystemForBaseType(typeSystemDefinition) ? typeSystemDefinition.getType().getName() : typeSystemDefinition.getTypeExtension().getName()), - Function.identity()) + (typeSystemDefinition -> isTypeSystemForBaseType(typeSystemDefinition) ? typeSystemDefinition.getType() + .getName() : typeSystemDefinition.getTypeExtension().getName()), + Function.identity()) ); HashMap> extensionEntitiesByNamespace = new HashMap<>(); extensionEntitiesByNamespace.put(source.getServiceProvider().getNameSpace(), extensionEntities); Map valueTypes = types.values().stream() - .filter(typeDefinition -> !definitionContainsDirective(typeDefinition, FEDERATION_KEY_DIRECTIVE)) - .collect(Collectors.toMap(TypeDefinition::getName, Function.identity())); - + .filter(typeDefinition -> !definitionContainsDirective(typeDefinition, FEDERATION_KEY_DIRECTIVE)) + .collect(Collectors.toMap(TypeDefinition::getName, Function.identity())); return source.transform(builder -> builder - .types(types) - .typeMetadatas(createTypeMetadatas(types)) - .valueTypesByName(valueTypes) - .entitiesByTypeName(baseEntities) - .entityExtensionsByNamespace(extensionEntitiesByNamespace) + .types(types) + .typeMetadatas(createTypeMetadatas(types)) + .valueTypesByName(valueTypes) + .entitiesByTypeName(baseEntities) + .entityExtensionsByNamespace(extensionEntitiesByNamespace) ); } return source.transform(builder -> builder - .types(types) - .typeMetadatas(createTypeMetadatas(types)) + .types(types) + .typeMetadatas(createTypeMetadatas(types)) ); } private Map createTypeMetadatas(Map types) { Map output = new HashMap<>(); types.forEach((typename, typeDefinition) -> - output.put(typename, new TypeMetadata(typeDefinition)) + output.put(typename, new TypeMetadata(typeDefinition)) ); return output; } @@ -119,7 +119,7 @@ private boolean isNotEmpty(TypeDefinition typeDefinition) { private void updateDescWithNamespace(Map types, String namespace) { types.forEach((k, v) -> { - v.setDesc(DescriptionUtils.attachNamespace(namespace,v.getDesc())); + v.setDesc(DescriptionUtils.attachNamespace(namespace, v.getDesc())); }); } } diff --git a/src/main/java/com/intuit/graphql/orchestrator/schema/transform/FederationTransformerPreMerge.java b/src/main/java/com/intuit/graphql/orchestrator/schema/transform/FederationTransformerPreMerge.java index 418638c7..b9dd1542 100644 --- a/src/main/java/com/intuit/graphql/orchestrator/schema/transform/FederationTransformerPreMerge.java +++ b/src/main/java/com/intuit/graphql/orchestrator/schema/transform/FederationTransformerPreMerge.java @@ -38,7 +38,7 @@ public class FederationTransformerPreMerge implements Transformer { diff --git a/src/main/java/com/intuit/graphql/orchestrator/stitching/XtextStitcher.java b/src/main/java/com/intuit/graphql/orchestrator/stitching/XtextStitcher.java index 11b1b9e7..5d8d0a83 100644 --- a/src/main/java/com/intuit/graphql/orchestrator/stitching/XtextStitcher.java +++ b/src/main/java/com/intuit/graphql/orchestrator/stitching/XtextStitcher.java @@ -23,15 +23,17 @@ import com.intuit.graphql.orchestrator.resolverdirective.ResolverArgumentQueryBuilder; import com.intuit.graphql.orchestrator.schema.Operation; import com.intuit.graphql.orchestrator.schema.RuntimeGraph; +import com.intuit.graphql.orchestrator.schema.ServiceMetadata; +import com.intuit.graphql.orchestrator.schema.ServiceMetadataImpl; import com.intuit.graphql.orchestrator.schema.fold.XtextGraphFolder; import com.intuit.graphql.orchestrator.schema.transform.AllTypesTransformer; import com.intuit.graphql.orchestrator.schema.transform.DirectivesTransformer; import com.intuit.graphql.orchestrator.schema.transform.DomainTypesTransformer; +import com.intuit.graphql.orchestrator.schema.transform.FederationTransformerPostMerge; import com.intuit.graphql.orchestrator.schema.transform.FederationTransformerPreMerge; import com.intuit.graphql.orchestrator.schema.transform.FieldResolverTransformerPostMerge; import com.intuit.graphql.orchestrator.schema.transform.FieldResolverTransformerPreMerge; import com.intuit.graphql.orchestrator.schema.transform.GraphQLAdapterTransformer; -import com.intuit.graphql.orchestrator.schema.transform.FederationTransformerPostMerge; import com.intuit.graphql.orchestrator.schema.transform.ResolverArgumentTransformer; import com.intuit.graphql.orchestrator.schema.transform.Transformer; import com.intuit.graphql.orchestrator.schema.transform.TypeExtensionTransformer; @@ -105,24 +107,30 @@ public RuntimeGraph stitch(List serviceProviders) { //Stitch Graphs XtextGraph stitchedGraph = new XtextGraphFolder().fold(XtextGraph.emptyGraph(), xtextGraphMap.values()); + //Service Metadata + final Map serviceMetadataMap = xtextGraphMap.values().parallelStream() + .map(this::buildServiceMetadata) + .collect(Collectors.toMap(metadata -> metadata.getServiceProvider().getNameSpace(), Function.identity())); + //Transform after merge XtextGraph stitchedTransformedGraph = transform(stitchedGraph, postMergeTransformers); //Executable RuntimeGraph with BatchLoaders and DataFetchers - final Map batchLoaders = getBatchLoaders(xtextGraphMap); + final Map batchLoaders = getBatchLoaders(serviceMetadataMap); stitchedTransformedGraph.getFieldResolverContexts().forEach(fieldResolverContext -> { FieldResolverBatchLoader fieldResolverDataLoader = FieldResolverBatchLoader - .builder() - .fieldResolverContext(fieldResolverContext) - .build(); + .builder() + .fieldResolverContext(fieldResolverContext) + .build(); String batchLoaderKey = FieldResolverDataLoaderUtil.createDataLoaderKeyFrom(fieldResolverContext); batchLoaders.put(batchLoaderKey, fieldResolverDataLoader); }); - final GraphQLCodeRegistry.Builder codeRegistryBuilder = getCodeRegistry(stitchedTransformedGraph, xtextGraphMap); + final GraphQLCodeRegistry.Builder codeRegistryBuilder = getCodeRegistry(stitchedTransformedGraph, + serviceMetadataMap); final RuntimeGraph.Builder runtimeGraphBuilder = createRuntimeGraph(stitchedTransformedGraph); @@ -139,19 +147,21 @@ public RuntimeGraph stitch(List serviceProviders) { /** * Creates a namespace vs batch loader map for corresponding data providers per graph * - * @param xtextGraphMap map of namespace vs xtext graph for all data providers + * @param serviceMetadataMap map of namespace vs xtext graph for all data providers * @return map of namespace vs batch loader */ - private Map getBatchLoaders(Map xtextGraphMap) { + private Map getBatchLoaders(Map serviceMetadataMap) { HashMap batchLoaderMap = new HashMap<>(); - xtextGraphMap.forEach((namespace, graph) -> { - if (graph.getServiceProvider().getSeviceType() == ServiceType.GRAPHQL || graph.getServiceProvider().isFederationProvider()) { + serviceMetadataMap.forEach((namespace, serviceMetadata) -> { + if (serviceMetadata.getServiceProvider().getSeviceType() == ServiceType.GRAPHQL || serviceMetadata + .getServiceProvider() + .isFederationProvider()) { batchLoaderMap.put(namespace, GraphQLServiceBatchLoader .newQueryExecutorBatchLoader() - .queryExecutor(graph.getServiceProvider()) - .serviceMetadata(graph) + .queryExecutor(serviceMetadata.getServiceProvider()) + .serviceMetadata(serviceMetadata) .batchLoaderExecutionHooks(batchLoaderHooks) .build()); } @@ -159,15 +169,25 @@ private Map getBatchLoaders(Map xtextGr return batchLoaderMap; } + private ServiceMetadata buildServiceMetadata(XtextGraph xtextGraph) { + return ServiceMetadataImpl.newBuilder() + .serviceProvider(xtextGraph.getServiceProvider()) + .typeMetadataMap(xtextGraph.getTypeMetadatas()) + .federationMetadata(xtextGraph.getFederationServiceMetadata()) + .hasFieldResolverDefinition(xtextGraph.isHasFieldResolverDefinition()) + .hasInterfaceOrUnion(xtextGraph.isHasInterfaceOrUnion()) + .build(); + } + /** * Builds GraphQL Code Registry for a xtext graph using field context and data fetcher context * * @param mergedGraph the post-merged and post-transformed graph - * @param graphsByNamespace the individual graphs that were used to build the merged graph + * @param serviceMetadataMap the individual graphs that were used to build the merged graph * @return GraphQL Code Registry Builder */ private GraphQLCodeRegistry.Builder getCodeRegistry(XtextGraph mergedGraph, - Map graphsByNamespace) { + Map serviceMetadataMap) { GraphQLCodeRegistry.Builder builder = GraphQLCodeRegistry.newCodeRegistry(); @@ -178,7 +198,8 @@ private GraphQLCodeRegistry.Builder getCodeRegistry(XtextGraph mergedGraph, if (type == STATIC) { builder.dataFetcher(coordinates, new StaticDataFetcher(Collections.emptyMap())); } else if (type == SERVICE) { - final XtextGraph serviceMetadata = graphsByNamespace.get(dataFetcherContext.getNamespace()); + final ServiceMetadata serviceMetadata = serviceMetadataMap.get(dataFetcherContext.getNamespace()); + builder.dataFetcher(coordinates, dataFetcherContext.getServiceType() == ServiceType.REST ? new RestDataFetcher(serviceMetadata) diff --git a/src/main/java/com/intuit/graphql/orchestrator/xtext/XtextGraph.java b/src/main/java/com/intuit/graphql/orchestrator/xtext/XtextGraph.java index e15deb68..dc28f273 100644 --- a/src/main/java/com/intuit/graphql/orchestrator/xtext/XtextGraph.java +++ b/src/main/java/com/intuit/graphql/orchestrator/xtext/XtextGraph.java @@ -12,11 +12,9 @@ import com.intuit.graphql.orchestrator.federation.metadata.FederationMetadata; import com.intuit.graphql.orchestrator.federation.metadata.FederationMetadata.EntityExtensionMetadata; import com.intuit.graphql.orchestrator.schema.Operation; -import com.intuit.graphql.orchestrator.schema.ServiceMetadata; import com.intuit.graphql.orchestrator.schema.TypeMetadata; import com.intuit.graphql.orchestrator.schema.transform.FieldResolverContext; import com.intuit.graphql.utils.XtextTypeUtils; -import graphql.schema.FieldCoordinates; import java.util.ArrayList; import java.util.EnumMap; import java.util.HashMap; @@ -24,7 +22,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Objects; import java.util.Set; import java.util.function.Consumer; import lombok.Getter; @@ -35,7 +32,7 @@ * batchloaders for optimization. */ @Getter -public class XtextGraph implements ServiceMetadata { +public class XtextGraph { private final ServiceProvider serviceProvider; private final XtextResourceSet xtextResourceSet; @@ -71,10 +68,7 @@ private XtextGraph(Builder builder) { //TODO: Research on all Providers having an XtextResource instead of a ResourceSet operationMap = builder.operationMap; codeRegistry = builder.codeRegistry; - for (DirectiveDefinition directiveDefinition : directives = builder.directives) { - - } - + directives = builder.directives; types = builder.types; typeMetadatas = builder.typeMetadatas; hasInterfaceOrUnion = builder.hasInterfaceOrUnion; @@ -125,9 +119,9 @@ public static Builder newBuilder(XtextGraph copy) { } /** - * Empty runtime graph. + * Empty Xtext graph. * - * @return the runtime graph + * @return the Xtext graph */ public static XtextGraph emptyGraph() { @@ -148,64 +142,14 @@ public static XtextGraph emptyGraph() { * * @return true or false */ - @Override public boolean requiresTypenameInjection() { return isHasInterfaceOrUnion(); } - @Override - public boolean hasFieldResolverDirective() { - return hasFieldResolverDefinition; - } - - @Override - public FieldResolverContext getFieldResolverContext(FieldCoordinates fieldCoordinates) { - TypeMetadata typeMetadata = this.typeMetadatas.get(fieldCoordinates.getTypeName()); - if (Objects.isNull(typeMetadata)) { - return null; - } - return typeMetadata.getFieldResolverContext(fieldCoordinates.getFieldName()); - } - - @Override - public boolean isOwnedByEntityExtension(FieldCoordinates fieldCoordinates) { - if (!this.serviceProvider.isFederationProvider()) { - return false; - } - - FederationMetadata federationMetadata = this.federationMetadataByNamespace.get(serviceProvider.getNameSpace()); - return federationMetadata.isFieldExternal(fieldCoordinates); - } - - @Override - public boolean isFederationService() { - return this.serviceProvider.isFederationProvider(); - } - - @Override - public boolean isEntity(String typename) { - return isFederationService() && getFederationServiceMetadata().isEntity(typename); - } - public FederationMetadata getFederationServiceMetadata() { return getFederationMetadataByNamespace().get(serviceProvider.getNameSpace()); } - /** - * Check if the given typeName exists in provider's schema. - * - * @param typeName typeName to check - * @return true or false - */ - @Override - public boolean hasType(String typeName) { - return types.containsKey(typeName); - } - - @Override - public boolean shouldRemoveExternalFields() { - return hasFieldResolverDirective() || isFederationService(); - } public TypeDefinition getType(final NamedType namedType) { return types.get(XtextTypeUtils.typeName(namedType)); @@ -296,6 +240,7 @@ public void addToEntityExtensionMetadatas(EntityExtensionMetadata entityExtensio this.entityExtensionMetadatas.add(entityExtensionMetadatas); } + /** * The type Builder. */ @@ -474,7 +419,8 @@ public Builder entitiesByTypeName(Map entities) { return this; } - public Builder entityExtensionsByNamespace(Map> entityExtensionsByNamespace) { + public Builder entityExtensionsByNamespace( + Map> entityExtensionsByNamespace) { requireNonNull(entityExtensionsByNamespace); this.entityExtensionsByNamespace.putAll(entityExtensionsByNamespace); return this; diff --git a/src/test/groovy/helpers/SchemaTestUtil.groovy b/src/test/groovy/helpers/SchemaTestUtil.groovy index c3ac932e..dbbeb63e 100644 --- a/src/test/groovy/helpers/SchemaTestUtil.groovy +++ b/src/test/groovy/helpers/SchemaTestUtil.groovy @@ -11,7 +11,7 @@ class SchemaTestUtil extends Specification { static RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring().build() - static defaultOptions = SchemaGenerator.Options.defaultOptions().enforceSchemaDirectives(false) + static defaultOptions = SchemaGenerator.Options.defaultOptions() static SchemaParser schemaParser = new SchemaParser() diff --git a/src/test/java/com/intuit/graphql/orchestrator/batch/GraphQLServiceBatchLoaderTest.java b/src/test/java/com/intuit/graphql/orchestrator/batch/GraphQLServiceBatchLoaderTest.java index d65790ef..6e395e9a 100644 --- a/src/test/java/com/intuit/graphql/orchestrator/batch/GraphQLServiceBatchLoaderTest.java +++ b/src/test/java/com/intuit/graphql/orchestrator/batch/GraphQLServiceBatchLoaderTest.java @@ -27,7 +27,7 @@ import com.intuit.graphql.orchestrator.ServiceProvider; import com.intuit.graphql.orchestrator.authorization.BatchFieldAuthorization; import com.intuit.graphql.orchestrator.batch.GraphQLTestUtil.PassthroughQueryModifier; -import com.intuit.graphql.orchestrator.xtext.XtextGraph; +import com.intuit.graphql.orchestrator.schema.ServiceMetadataImpl; import graphql.GraphQLContext; import graphql.Scalars; import graphql.execution.ExecutionStepInfo; @@ -75,7 +75,7 @@ public class GraphQLServiceBatchLoaderTest { public ServiceProvider mockServiceProvider; @Mock - public XtextGraph mockServiceMetadata; + public ServiceMetadataImpl mockServiceMetadata; @Mock public VariableDefinitionFilter mockVariableDefinitionFilter; @@ -506,7 +506,7 @@ public void propagatesVariableDefinitions() { final MergedField mergedFieldWithArgument = newMergedField( newField("fieldWithArgument").arguments( singletonList(Argument.newArgument("SomeArgument", - newVariableReference().name("TestVariableDefinition").build()) + newVariableReference().name("TestVariableDefinition").build()) .build())).build()).build(); final ExecutionStepInfo root = ExecutionStepInfo.newExecutionStepInfo() @@ -778,7 +778,6 @@ public void fragmentDefinitionCallTest() { .selection(FragmentSpread.newFragmentSpread("firstFrag").build()) .selection(FragmentSpread.newFragmentSpread("secondFrag").build()).build()).build()).build(); - GraphQLSchema graphQLSchema = newSchema() .query(queryType).build(); @@ -804,7 +803,6 @@ public void fragmentDefinitionCallTest() { m.put("firstFrag", fdb1); m.put("secondFrag", fdb2); - DataFetchingEnvironment dfe1 = newDataFetchingEnvironment() .variables(ImmutableMap.of("1", "3")) .graphQLSchema(graphQLSchema) diff --git a/src/test/java/com/intuit/graphql/orchestrator/datafetcher/RestDataFetcherTest.java b/src/test/java/com/intuit/graphql/orchestrator/datafetcher/RestDataFetcherTest.java index 70941a39..bc483ac0 100644 --- a/src/test/java/com/intuit/graphql/orchestrator/datafetcher/RestDataFetcherTest.java +++ b/src/test/java/com/intuit/graphql/orchestrator/datafetcher/RestDataFetcherTest.java @@ -10,7 +10,7 @@ import com.intuit.graphql.orchestrator.TestServiceProvider; import com.intuit.graphql.orchestrator.batch.QueryExecutor; import com.intuit.graphql.orchestrator.schema.ServiceMetadata; -import com.intuit.graphql.orchestrator.xtext.XtextGraph; +import com.intuit.graphql.orchestrator.schema.ServiceMetadataImpl; import graphql.GraphQLContext; import graphql.execution.DataFetcherResult; import graphql.execution.MergedField; @@ -85,7 +85,7 @@ public void canExecuteRequest() { TestServiceProvider testServiceProvider = TestServiceProvider.newBuilder().queryFunction(queryExecutor) .serviceType(ServiceType.REST).build(); - ServiceMetadata serviceMetadata = mock(XtextGraph.class); + ServiceMetadata serviceMetadata = mock(ServiceMetadataImpl.class); when(serviceMetadata.getServiceProvider()).thenReturn(testServiceProvider); RestDataFetcher restDataFetcher = new RestDataFetcher(serviceMetadata); diff --git a/src/test/java/com/intuit/graphql/orchestrator/schema/transform/FieldResolverTransformerPostMergeTest.java b/src/test/java/com/intuit/graphql/orchestrator/schema/transform/FieldResolverTransformerPostMergeTest.java index 7a9684fe..4d965bb4 100644 --- a/src/test/java/com/intuit/graphql/orchestrator/schema/transform/FieldResolverTransformerPostMergeTest.java +++ b/src/test/java/com/intuit/graphql/orchestrator/schema/transform/FieldResolverTransformerPostMergeTest.java @@ -84,7 +84,7 @@ public void transformSchemaWithoutResolverDirectiveOnFieldDefinitionNoProcessing + "} " + "directive @resolver(field: String) on ARGUMENT_DEFINITION"; XtextGraph xtextGraph = createTestXtextGraph(schema); - assertThat(xtextGraph.hasFieldResolverDirective()).isFalse(); + assertThat(xtextGraph.isHasFieldResolverDefinition()).isFalse(); XtextGraph textGraphSpy = Mockito.spy(xtextGraph); diff --git a/src/test/java/com/intuit/graphql/orchestrator/schema/transform/FieldResolverTransformerPreMergeTest.java b/src/test/java/com/intuit/graphql/orchestrator/schema/transform/FieldResolverTransformerPreMergeTest.java index 1f734bf8..de3f5814 100644 --- a/src/test/java/com/intuit/graphql/orchestrator/schema/transform/FieldResolverTransformerPreMergeTest.java +++ b/src/test/java/com/intuit/graphql/orchestrator/schema/transform/FieldResolverTransformerPreMergeTest.java @@ -36,27 +36,27 @@ public void transformWithNoFieldResolverSuccessNoTransformation() { + "} " + "directive @resolver(field: String) on ARGUMENT_DEFINITION"; XtextGraph xtextGraph = createTestXtextGraph(schema); - assertThat(xtextGraph.hasFieldResolverDirective()).isFalse(); + assertThat(xtextGraph.isHasFieldResolverDefinition()).isFalse(); // WHEN final XtextGraph transformedSource = transformer.transform(xtextGraph); // THEN assertThat(transformedSource.getCodeRegistry().size()).isEqualTo(0); - assertThat(transformedSource.hasFieldResolverDirective()).isFalse(); + assertThat(transformedSource.isHasFieldResolverDefinition()).isFalse(); } @Test public void transformWithFieldResolverSuccess() { // GIVEN XtextGraph xtextGraph = createTestXtextGraph(SCHEMA_A_IS_OBJECT_TYPE); - assertThat(xtextGraph.hasFieldResolverDirective()).isFalse(); + assertThat(xtextGraph.isHasFieldResolverDefinition()).isFalse(); // WHEN final XtextGraph transformedSource = transformer.transform(xtextGraph); // THEN - assertThat(transformedSource.hasFieldResolverDirective()).isTrue(); + assertThat(transformedSource.isHasFieldResolverDefinition()).isTrue(); assertThat(transformedSource.getFieldResolverContexts().size()).isEqualTo(1); FieldResolverContext actualFieldResolverContext = transformedSource.getFieldResolverContexts().get(0); @@ -68,13 +68,13 @@ public void transformWithFieldResolverSuccess() { public void transformWithFieldResolverParentNotNullSuccess() { // GIVEN XtextGraph xtextGraph = createTestXtextGraph(SCHEMA_A_TYPE_IS_NOT_NULL); - assertThat(xtextGraph.hasFieldResolverDirective()).isFalse(); + assertThat(xtextGraph.isHasFieldResolverDefinition()).isFalse(); // WHEN final XtextGraph transformedSource = transformer.transform(xtextGraph); // THEN - assertThat(transformedSource.hasFieldResolverDirective()).isTrue(); + assertThat(transformedSource.isHasFieldResolverDefinition()).isTrue(); assertThat(transformedSource.getFieldResolverContexts().size()).isEqualTo(1); FieldResolverContext actualFieldResolverContext = transformedSource.getFieldResolverContexts().get(0); @@ -86,13 +86,13 @@ public void transformWithFieldResolverParentNotNullSuccess() { public void transformWithFieldResolverParentWrappedInArraySuccess() { // GIVEN XtextGraph xtextGraph = createTestXtextGraph(SCHEMA_A_TYPE_WRAPPED_IN_ARRAY); - assertThat(xtextGraph.hasFieldResolverDirective()).isFalse(); + assertThat(xtextGraph.isHasFieldResolverDefinition()).isFalse(); // WHEN final XtextGraph transformedSource = transformer.transform(xtextGraph); // THEN - assertThat(transformedSource.hasFieldResolverDirective()).isTrue(); + assertThat(transformedSource.isHasFieldResolverDefinition()).isTrue(); assertThat(transformedSource.getFieldResolverContexts().size()).isEqualTo(1); FieldResolverContext actualFieldResolverContext = transformedSource.getFieldResolverContexts().get(0); @@ -104,13 +104,13 @@ public void transformWithFieldResolverParentWrappedInArraySuccess() { public void transformWithFieldResolverParentNotNullWrappedInArraySuccess() { // GIVEN XtextGraph xtextGraph = createTestXtextGraph(SCHEMA_A_NOT_NULL_WRAPPED_IN_ARRAY); - assertThat(xtextGraph.hasFieldResolverDirective()).isFalse(); + assertThat(xtextGraph.isHasFieldResolverDefinition()).isFalse(); // WHEN final XtextGraph transformedSource = transformer.transform(xtextGraph); // THEN - assertThat(transformedSource.hasFieldResolverDirective()).isTrue(); + assertThat(transformedSource.isHasFieldResolverDefinition()).isTrue(); assertThat(transformedSource.getFieldResolverContexts().size()).isEqualTo(1); FieldResolverContext actualFieldResolverContext = transformedSource.getFieldResolverContexts().get(0); @@ -121,26 +121,26 @@ public void transformWithFieldResolverParentNotNullWrappedInArraySuccess() { @Test public void transformWithTwoFieldResolversYieldsTwoFieldResolverContext() { XtextGraph xtextGraph = createTestXtextGraph(SCHEMA_A_WITH_TWO__FIELD_RESOLVERS); - assertThat(xtextGraph.hasFieldResolverDirective()).isFalse(); + assertThat(xtextGraph.isHasFieldResolverDefinition()).isFalse(); // WHEN final XtextGraph transformedSource = transformer.transform(xtextGraph); // THEN - assertThat(transformedSource.hasFieldResolverDirective()).isTrue(); + assertThat(transformedSource.isHasFieldResolverDefinition()).isTrue(); assertThat(transformedSource.getFieldResolverContexts().size()).isEqualTo(2); } @Test public void transformTwoTypesWithFieldWithResolverYieldsTwoFieldResolverContexts() { XtextGraph xtextGraph = createTestXtextGraph(SCHEMA_A_AND_C_WITH_WITH_FIELD_RESOLVER); - assertThat(xtextGraph.hasFieldResolverDirective()).isFalse(); + assertThat(xtextGraph.isHasFieldResolverDefinition()).isFalse(); // WHEN final XtextGraph transformedSource = transformer.transform(xtextGraph); // THEN - assertThat(transformedSource.hasFieldResolverDirective()).isTrue(); + assertThat(transformedSource.isHasFieldResolverDefinition()).isTrue(); assertThat(transformedSource.getFieldResolverContexts().size()).isEqualTo(2); } @@ -148,7 +148,7 @@ public void transformTwoTypesWithFieldWithResolverYieldsTwoFieldResolverContexts public void transformWithFieldResolverParentIsAnInterfaceThrowsException() { // GIVEN XtextGraph xtextGraph = createTestXtextGraph(SCHEMA_A_IS_INTERFACE); - assertThat(xtextGraph.hasFieldResolverDirective()).isFalse(); + assertThat(xtextGraph.isHasFieldResolverDefinition()).isFalse(); exceptionRule.expect(NotAValidLocationForFieldResolverDirective.class); @@ -160,7 +160,7 @@ public void transformWithFieldResolverParentIsAnInterfaceThrowsException() { public void transformWithFieldDefinitionResolveHasArgumentThrowsException() { // GIVEN XtextGraph xtextGraph = createTestXtextGraph(SCHEMA_FIELD_WITH_RESOLVER_HAS_ARGUMENT); - assertThat(xtextGraph.hasFieldResolverDirective()).isFalse(); + assertThat(xtextGraph.isHasFieldResolverDefinition()).isFalse(); exceptionRule.expect(ArgumentDefinitionNotAllowed.class); From 19005b75d4dda31dab212fbd25d503c392aa0c66 Mon Sep 17 00:00:00 2001 From: bshah6 Date: Wed, 1 Jun 2022 11:32:14 -0700 Subject: [PATCH 2/2] remove parallel streams --- .../intuit/graphql/orchestrator/stitching/XtextStitcher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/intuit/graphql/orchestrator/stitching/XtextStitcher.java b/src/main/java/com/intuit/graphql/orchestrator/stitching/XtextStitcher.java index 5d8d0a83..782a6c89 100644 --- a/src/main/java/com/intuit/graphql/orchestrator/stitching/XtextStitcher.java +++ b/src/main/java/com/intuit/graphql/orchestrator/stitching/XtextStitcher.java @@ -108,7 +108,7 @@ public RuntimeGraph stitch(List serviceProviders) { XtextGraph stitchedGraph = new XtextGraphFolder().fold(XtextGraph.emptyGraph(), xtextGraphMap.values()); //Service Metadata - final Map serviceMetadataMap = xtextGraphMap.values().parallelStream() + final Map serviceMetadataMap = xtextGraphMap.values().stream() .map(this::buildServiceMetadata) .collect(Collectors.toMap(metadata -> metadata.getServiceProvider().getNameSpace(), Function.identity()));