Schema inspection handles List from Subscription

Normally a multivalue Publisher is collected to a List, so we can treat
it as a match for a List field. For subscriptions, however, such a
Publisher is left as an infinite stream, and we should not treat as a
match for a List, but rather expect it to be a stream of List items.

Discovered while working on gh-674, which is closely related.
This commit is contained in:
rstoyanchev
2023-04-25 17:59:49 +01:00
parent 133b4063e4
commit d4b2266ff7
2 changed files with 17 additions and 15 deletions

View File

@@ -112,14 +112,14 @@ class SchemaMappingInspector {
*/
public Report inspect() {
inspectSchemaType(this.schema.getQueryType(), null);
inspectSchemaType(this.schema.getQueryType(), null, false);
if (this.schema.isSupportingMutations()) {
inspectSchemaType(this.schema.getMutationType(), null);
inspectSchemaType(this.schema.getMutationType(), null, false);
}
if (this.schema.isSupportingSubscriptions()) {
inspectSchemaType(this.schema.getSubscriptionType(), null);
inspectSchemaType(this.schema.getSubscriptionType(), null, false);
}
inspectDataFetcherRegistrations();
@@ -128,7 +128,7 @@ class SchemaMappingInspector {
}
@SuppressWarnings("rawtypes")
private void inspectSchemaType(GraphQLType type, @Nullable ResolvableType resolvableType) {
private void inspectSchemaType(GraphQLType type, @Nullable ResolvableType resolvableType, boolean subscription) {
Assert.notNull(type, "No GraphQLType");
type = unwrapNonNull(type);
@@ -138,7 +138,7 @@ class SchemaMappingInspector {
}
else if (type instanceof GraphQLList listType) {
type = unwrapNonNull(listType.getWrappedType());
resolvableType = nestForList(resolvableType, type);
resolvableType = nestForList(resolvableType, type, subscription);
}
else {
resolvableType = (resolvableType != null ? nestIfReactive(resolvableType) : null);
@@ -177,7 +177,9 @@ class SchemaMappingInspector {
if (dataFetcherMap.containsKey(fieldName)) {
DataFetcher<?> fetcher = dataFetcherMap.get(fieldName);
if (fetcher instanceof SelfDescribingDataFetcher<?> selfDescribingDataFetcher) {
inspectSchemaType(field.getType(), selfDescribingDataFetcher.getReturnType());
inspectSchemaType(
field.getType(), selfDescribingDataFetcher.getReturnType(),
(type == this.schema.getSubscriptionType()));
}
else if (isNotScalarOrEnumType(field.getType())) {
if (logger.isDebugEnabled()) {
@@ -228,15 +230,15 @@ class SchemaMappingInspector {
return type;
}
private ResolvableType nestForList(@Nullable ResolvableType type, GraphQLType graphQlType) {
private ResolvableType nestForList(@Nullable ResolvableType type, GraphQLType graphQlType, boolean subscription) {
Assert.state(type != null, "No Java type for " + getTypeName(graphQlType));
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(type.resolve(Object.class));
if (adapter != null) {
if (adapter.isMultiValue()) {
return type.getNested(2);
}
Assert.state(!adapter.isNoValue(), "Expected List compatible type: " + type);
type = type.getNested(2);
if (adapter.isMultiValue() && !subscription) {
return type;
}
}
Assert.state(type.isArray() || type.hasGenerics(), "Expected List compatible type: " + type);
return type.getNested(2);

View File

@@ -219,7 +219,7 @@ class SchemaMappingInspectorTests {
greeting: String
}
type Subscription {
bookSearch(author: String) : Book!
bookSearch(author: String) : [Book!]!
}
type Book {
@@ -238,7 +238,7 @@ class SchemaMappingInspectorTests {
greeting: String
}
type Subscription {
bookSearch(author: String) : Book!
bookSearch(author: String) : [Book!]!
}
type Book {
@@ -259,7 +259,7 @@ class SchemaMappingInspectorTests {
type Subscription {
}
extend type Subscription {
bookSearch(author: String) : Book!
bookSearch(author: String) : [Book!]!
}
type Book {
id: ID
@@ -493,7 +493,7 @@ class SchemaMappingInspectorTests {
createBook: Book
}
type Subscription {
bookSearch(author: String) : Book!
bookSearch(author: String) : [Book!]!
}
type Book {
id: ID
@@ -598,7 +598,7 @@ class SchemaMappingInspectorTests {
}
@SubscriptionMapping
public Flux<Book> bookSearch(@Argument String author) {
public Flux<List<Book>> bookSearch(@Argument String author) {
return Flux.empty();
}
}