graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentation Maven / Gradle / Ivy
package graphql.execution.instrumentation.dataloader;
import graphql.ExecutionResult;
import graphql.ExecutionResultImpl;
import graphql.PublicApi;
import graphql.collect.ImmutableKit;
import graphql.execution.AsyncExecutionStrategy;
import graphql.execution.ExecutionContext;
import graphql.execution.ExecutionStrategy;
import graphql.execution.instrumentation.ExecutionStrategyInstrumentationContext;
import graphql.execution.instrumentation.InstrumentationContext;
import graphql.execution.instrumentation.InstrumentationState;
import graphql.execution.instrumentation.SimpleInstrumentation;
import graphql.execution.instrumentation.SimpleInstrumentationContext;
import graphql.execution.instrumentation.parameters.InstrumentationCreateStateParameters;
import graphql.execution.instrumentation.parameters.InstrumentationExecuteOperationParameters;
import graphql.execution.instrumentation.parameters.InstrumentationExecutionParameters;
import graphql.execution.instrumentation.parameters.InstrumentationExecutionStrategyParameters;
import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters;
import graphql.language.OperationDefinition;
import graphql.schema.DataFetcher;
import org.dataloader.DataLoader;
import org.dataloader.DataLoaderRegistry;
import org.dataloader.stats.Statistics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
/**
* This graphql {@link graphql.execution.instrumentation.Instrumentation} will dispatch
* all the contained {@link org.dataloader.DataLoader}s when each level of the graphql
* query is executed.
*
* This allows you to use {@link org.dataloader.DataLoader}s in your {@link graphql.schema.DataFetcher}s
* to optimal loading of data.
*
* A DataLoaderDispatcherInstrumentation will be automatically added to the {@link graphql.GraphQL}
* instrumentation list if one is not present.
*
* @see org.dataloader.DataLoader
* @see org.dataloader.DataLoaderRegistry
*/
@PublicApi
public class DataLoaderDispatcherInstrumentation extends SimpleInstrumentation {
private static final Logger log = LoggerFactory.getLogger(DataLoaderDispatcherInstrumentation.class);
private final DataLoaderDispatcherInstrumentationOptions options;
/**
* Creates a DataLoaderDispatcherInstrumentation with the default options
*/
public DataLoaderDispatcherInstrumentation() {
this(DataLoaderDispatcherInstrumentationOptions.newOptions());
}
/**
* Creates a DataLoaderDispatcherInstrumentation with the specified options
*
* @param options the options to control the behaviour
*/
public DataLoaderDispatcherInstrumentation(DataLoaderDispatcherInstrumentationOptions options) {
this.options = options;
}
@Override
public InstrumentationState createState(InstrumentationCreateStateParameters parameters) {
return new DataLoaderDispatcherInstrumentationState(log, parameters.getExecutionInput().getDataLoaderRegistry());
}
@Override
public DataFetcher> instrumentDataFetcher(DataFetcher> dataFetcher, InstrumentationFieldFetchParameters parameters) {
DataLoaderDispatcherInstrumentationState state = parameters.getInstrumentationState();
if (state.isAggressivelyBatching()) {
return dataFetcher;
}
//
// currently only AsyncExecutionStrategy with DataLoader and hence this allows us to "dispatch"
// on every object if its not using aggressive batching for other execution strategies
// which allows them to work if used.
return (DataFetcher