Support use of dataloader from suspend function
Rudimentary implementation to support returning a `CompletableFuture` from a suspend function. `CoroutinesUtils.invokeSuspendingFunction` wraps the return value of the function in a `Mono` (or `Flux`). But it also does this when a `CompletableFuture` is returned, and thus results in a `Mono<CompletableFuture<?>>`, which isn't captured by graphql-java, and thus the dataloader is never dispatched. By unwrapping the future, and _converting_ it to a mono (as opposed to wrapping), the dataloader is dispatched correctly. See gh-653
This commit is contained in:
@@ -26,6 +26,7 @@ import java.util.concurrent.Executor;
|
||||
|
||||
import graphql.GraphQLContext;
|
||||
import io.micrometer.context.ContextSnapshot;
|
||||
import org.springframework.data.util.KotlinReflectionUtils;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.CoroutinesUtils;
|
||||
@@ -81,7 +82,18 @@ public abstract class InvocableHandlerMethodSupport extends HandlerMethod {
|
||||
Method method = getBridgedMethod();
|
||||
try {
|
||||
if (KotlinDetector.isSuspendingFunction(method)) {
|
||||
return CoroutinesUtils.invokeSuspendingFunction(method, getBean(), argValues);
|
||||
Object result = CoroutinesUtils.invokeSuspendingFunction(method, getBean(), argValues);
|
||||
|
||||
Class<?> returnType = KotlinReflectionUtils.getReturnType(method);
|
||||
|
||||
if (CompletableFuture.class.isAssignableFrom(returnType)) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Mono<CompletableFuture<?>> mono = (Mono<CompletableFuture<?>>)result;
|
||||
// Unwrap nested CompletableFuture
|
||||
return mono.flatMap(Mono::fromFuture);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
Object result = method.invoke(getBean(), argValues);
|
||||
return handleReturnValue(graphQLContext, result);
|
||||
|
||||
Reference in New Issue
Block a user