Polishing in SelfDescribingDataFetcher

This commit is contained in:
rstoyanchev
2025-04-17 14:48:23 +01:00
parent 7b728feaf3
commit cea4e08011
7 changed files with 58 additions and 60 deletions

View File

@@ -464,13 +464,12 @@ public class AnnotatedControllerConfigurer
this.executor = executor;
this.invokeAsync = invokeAsync;
this.subscription = this.mappingInfo.getCoordinates().getTypeName().equalsIgnoreCase("Subscription");
this.usesDataLoader = hasDataLoaderParameter();
this.usesDataLoader = hasDataLoaderParameter(info.getHandlerMethod());
}
private boolean hasDataLoaderParameter() {
Method handlerMethod = this.mappingInfo.getHandlerMethod().getMethod();
for (Class<?> parameterType : handlerMethod.getParameterTypes()) {
if (DataLoader.class.equals(parameterType)) {
private static boolean hasDataLoaderParameter(HandlerMethod method) {
for (MethodParameter type : method.getMethodParameters()) {
if (DataLoader.class.equals(type.getParameterType())) {
return true;
}
}
@@ -484,7 +483,11 @@ public class AnnotatedControllerConfigurer
@Override
public ResolvableType getReturnType() {
return ResolvableType.forMethodReturnType(this.mappingInfo.getHandlerMethod().getMethod());
return ResolvableType.forMethodReturnType(getHandlerMethod().getMethod());
}
HandlerMethod getHandlerMethod() {
return this.mappingInfo.getHandlerMethod();
}
@Override
@@ -493,7 +496,7 @@ public class AnnotatedControllerConfigurer
Predicate<MethodParameter> argumentPredicate = (p) ->
(p.getParameterAnnotation(Argument.class) != null || p.getParameterType() == ArgumentValue.class);
return Arrays.stream(this.mappingInfo.getHandlerMethod().getMethodParameters())
return Arrays.stream(getHandlerMethod().getMethodParameters())
.filter(argumentPredicate)
.peek((p) -> p.initParameterNameDiscovery(parameterNameDiscoverer))
.collect(Collectors.toMap(
@@ -501,11 +504,9 @@ public class AnnotatedControllerConfigurer
ResolvableType::forMethodParameter));
}
/**
* Return the {@link HandlerMethod} used to fetch data.
*/
HandlerMethod getHandlerMethod() {
return this.mappingInfo.getHandlerMethod();
@Override
public boolean usesDataLoader() {
return this.usesDataLoader;
}
@Override
@@ -564,11 +565,6 @@ public class AnnotatedControllerConfigurer
.switchIfEmpty(Mono.error(ex));
}
@Override
public boolean isBatchLoading() {
return this.usesDataLoader;
}
@Override
public String toString() {
return getDescription();
@@ -614,7 +610,7 @@ public class AnnotatedControllerConfigurer
}
@Override
public boolean isBatchLoading() {
public boolean usesDataLoader() {
return true;
}

View File

@@ -150,17 +150,6 @@ class ContextDataFetcherDecorator implements DataFetcher<Object> {
return new ContextTypeVisitor(resolvers);
}
private static ContextDataFetcherDecorator decorate(
DataFetcher<?> delegate, boolean handlesSubscription,
SubscriptionExceptionResolver subscriptionExceptionResolver) {
if (delegate instanceof SelfDescribingDataFetcher<?> selfDescribingDataFetcher) {
return new SelfDescribingDecorator(selfDescribingDataFetcher, handlesSubscription, subscriptionExceptionResolver);
}
else {
return new ContextDataFetcherDecorator(delegate, handlesSubscription, subscriptionExceptionResolver);
}
}
/**
* Type visitor to apply {@link ContextDataFetcherDecorator}.
@@ -185,8 +174,8 @@ class ContextDataFetcherDecorator implements DataFetcher<Object> {
DataFetcher<?> dataFetcher = codeRegistry.getDataFetcher(fieldCoordinates, fieldDefinition);
if (applyDecorator(dataFetcher)) {
boolean handlesSubscription = visitorHelper.isSubscriptionType(parent);
dataFetcher = ContextDataFetcherDecorator.decorate(dataFetcher, handlesSubscription, this.exceptionResolver);
boolean subscriptionType = visitorHelper.isSubscriptionType(parent);
dataFetcher = decorate(dataFetcher, subscriptionType, this.exceptionResolver);
codeRegistry.dataFetcher(fieldCoordinates, dataFetcher);
}
@@ -205,37 +194,48 @@ class ContextDataFetcherDecorator implements DataFetcher<Object> {
}
return true;
}
private static ContextDataFetcherDecorator decorate(
DataFetcher<?> dataFetcher, boolean subscriptionType, SubscriptionExceptionResolver exceptionResolver) {
return ((dataFetcher instanceof SelfDescribingDataFetcher<?> sddf) ?
new SelfDescribingContextDataFetcherDecorator(sddf, subscriptionType, exceptionResolver) :
new ContextDataFetcherDecorator(dataFetcher, subscriptionType, exceptionResolver));
}
}
private static final class SelfDescribingDecorator extends ContextDataFetcherDecorator implements SelfDescribingDataFetcher<Object> {
private final SelfDescribingDataFetcher<?> selfDescribingDataFetcher;
private static final class SelfDescribingContextDataFetcherDecorator extends ContextDataFetcherDecorator
implements SelfDescribingDataFetcher<Object> {
private SelfDescribingDecorator(
SelfDescribingDataFetcher<?> delegate, boolean subscription,
SubscriptionExceptionResolver subscriptionExceptionResolver) {
super(delegate, subscription, subscriptionExceptionResolver);
this.selfDescribingDataFetcher = delegate;
}
private final SelfDescribingDataFetcher<?> delegate;
@Override
public boolean isBatchLoading() {
return this.selfDescribingDataFetcher.isBatchLoading();
}
private SelfDescribingContextDataFetcherDecorator(
SelfDescribingDataFetcher<?> delegate, boolean subscriptionType,
SubscriptionExceptionResolver exceptionResolver) {
@Override
public Map<String, ResolvableType> getArguments() {
return this.selfDescribingDataFetcher.getArguments();
}
@Override
public ResolvableType getReturnType() {
return this.selfDescribingDataFetcher.getReturnType();
super(delegate, subscriptionType, exceptionResolver);
this.delegate = delegate;
}
@Override
public String getDescription() {
return this.selfDescribingDataFetcher.getDescription();
return this.delegate.getDescription();
}
@Override
public ResolvableType getReturnType() {
return this.delegate.getReturnType();
}
@Override
public Map<String, ResolvableType> getArguments() {
return this.delegate.getArguments();
}
@Override
public boolean usesDataLoader() {
return this.delegate.usesDataLoader();
}
}

View File

@@ -60,11 +60,13 @@ public interface SelfDescribingDataFetcher<T> extends DataFetcher<T> {
}
/**
* Return whether this {@code DataFetcher} is using batch loading.
* @return {@code true} if the data fetcher is batch loading elements
* Whether this {@code DataFetcher} uses a {@link org.dataloader.DataLoader}
* to return data. This represents a deferred operation that is typically
* repeatable, and a candidate for aggregation from a metrics and tracing
* perspective.
* @since 1.4.0
*/
default boolean isBatchLoading() {
default boolean usesDataLoader() {
return false;
}

View File

@@ -187,7 +187,7 @@ public class GraphQlObservationInstrumentation extends SimplePerformantInstrumen
&& state == RequestObservationInstrumentationState.INSTANCE) {
// skip batch loading operations, already instrumented at the dataloader level
if (dataFetcher instanceof SelfDescribingDataFetcher<?> selfDescribingDataFetcher
&& selfDescribingDataFetcher.isBatchLoading()) {
&& selfDescribingDataFetcher.usesDataLoader()) {
return dataFetcher;
}
return (environment) -> {

View File

@@ -83,7 +83,7 @@ class BatchMappingDetectionTests {
initRuntimeWiringBuilder(BookController.class).build().getDataFetchers();
assertThat(dataFetcherMap.get("Book").values()).allMatch(dataFetcher ->
dataFetcher instanceof SelfDescribingDataFetcher<?> selfDescribingDataFetcher
&& selfDescribingDataFetcher.isBatchLoading());
&& selfDescribingDataFetcher.usesDataLoader());
}
@Test

View File

@@ -91,13 +91,13 @@ class SchemaMappingDetectionTests {
Map<String, DataFetcher> queries = map.get("Book");
assertThat(queries.values()).allMatch(dataFetcher ->
dataFetcher instanceof SelfDescribingDataFetcher<?> selfDescribingDataFetcher
&& !selfDescribingDataFetcher.isBatchLoading());
&& !selfDescribingDataFetcher.usesDataLoader());
map = initRuntimeWiringBuilder(BatchLoadingController.class).build().getDataFetchers();
queries = map.get("Book");
assertThat(queries.values()).allMatch(dataFetcher ->
dataFetcher instanceof SelfDescribingDataFetcher<?> selfDescribingDataFetcher
&& selfDescribingDataFetcher.isBatchLoading());
&& selfDescribingDataFetcher.usesDataLoader());
}
private RuntimeWiring.Builder initRuntimeWiringBuilder(Class<?> handlerType) {

View File

@@ -419,7 +419,7 @@ class GraphQlObservationInstrumentationTests {
static class AuthorBatchLoadingDataFetcher implements SelfDescribingDataFetcher<CompletableFuture<Author>> {
@Override
public boolean isBatchLoading() {
public boolean usesDataLoader() {
return true;
}