All Downloads are FREE. Search and download functionalities are using the official Maven repository.

graphql.execution.ExecutorServiceExecutionStrategy Maven / Gradle / Ivy

There is a newer version: 230521-nf-execution
Show newest version
package graphql.execution;

import graphql.ExecutionResult;
import graphql.ExecutionResultImpl;
import graphql.GraphQLException;
import graphql.PublicApi;
import graphql.execution.instrumentation.Instrumentation;
import graphql.execution.instrumentation.InstrumentationContext;
import graphql.execution.instrumentation.parameters.InstrumentationExecutionStrategyParameters;
import graphql.language.Field;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

/**
 * 

ExecutorServiceExecutionStrategy uses an {@link ExecutorService} to parallelize the resolve.

* * Due to the nature of {@link #execute(ExecutionContext, ExecutionStrategyParameters)} implementation, {@link ExecutorService} * MUST have the following 2 characteristics: *
    *
  • 1. The underlying {@link java.util.concurrent.ThreadPoolExecutor} MUST have a reasonable {@code maximumPoolSize} *
  • 2. The underlying {@link java.util.concurrent.ThreadPoolExecutor} SHALL NOT use its task queue. *
* *

Failure to follow 1. and 2. can result in a very large number of threads created or hanging. (deadlock)

* * See {@code graphql.execution.ExecutorServiceExecutionStrategyTest} for example usage. */ @PublicApi public class ExecutorServiceExecutionStrategy extends ExecutionStrategy { final ExecutorService executorService; public ExecutorServiceExecutionStrategy(ExecutorService executorService) { this(executorService, new SimpleDataFetcherExceptionHandler()); } public ExecutorServiceExecutionStrategy(ExecutorService executorService, DataFetcherExceptionHandler dataFetcherExceptionHandler) { super(dataFetcherExceptionHandler); this.executorService = executorService; } @Override public CompletableFuture execute(final ExecutionContext executionContext, final ExecutionStrategyParameters parameters) { if (executorService == null) { return new AsyncExecutionStrategy().execute(executionContext, parameters); } Instrumentation instrumentation = executionContext.getInstrumentation(); InstrumentationExecutionStrategyParameters instrumentationParameters = new InstrumentationExecutionStrategyParameters(executionContext); InstrumentationContext> executionStrategyCtx = instrumentation.beginExecutionStrategy(instrumentationParameters); InstrumentationContext>> beginFieldsCtx = instrumentation.beginFields(instrumentationParameters); Map> fields = parameters.fields(); Map>> futures = new LinkedHashMap<>(); for (String fieldName : fields.keySet()) { final List currentField = fields.get(fieldName); ExecutionPath fieldPath = parameters.path().segment(fieldName); ExecutionStrategyParameters newParameters = parameters .transform(builder -> builder.field(currentField).path(fieldPath)); Callable> resolveField = () -> resolveField(executionContext, newParameters); futures.put(fieldName, executorService.submit(resolveField)); } beginFieldsCtx.onEnd(fields, null); try { Map results = new LinkedHashMap<>(); for (String fieldName : futures.keySet()) { ExecutionResult executionResult; try { executionResult = futures.get(fieldName).get().join(); } catch (CompletionException e) { if (e.getCause() instanceof NonNullableFieldWasNullException) { assertNonNullFieldPrecondition((NonNullableFieldWasNullException) e.getCause()); results = null; break; } else { throw e; } } results.put(fieldName, executionResult != null ? executionResult.getData() : null); } CompletableFuture result = CompletableFuture.completedFuture(new ExecutionResultImpl(results, executionContext.getErrors())); executionStrategyCtx.onEnd(result, null); return result; } catch (InterruptedException | ExecutionException e) { executionStrategyCtx.onEnd(null, e); throw new GraphQLException(e); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy