use of graphql.execution.instrumentation.Instrumentation in project graphql-java by graphql-java.
the class ExecutionStrategy method fetchField.
/**
* Called to fetch a value for a field from the {@link DataFetcher} associated with the field
* {@link GraphQLFieldDefinition}.
* <p>
* Graphql fragments mean that for any give logical field can have one or more {@link Field} values associated with it
* in the query, hence the fieldList. However the first entry is representative of the field for most purposes.
*
* @param executionContext contains the top level execution parameters
* @param parameters contains the parameters holding the fields to be executed and source object
*
* @return a fetched object
*
* @throws NonNullableFieldWasNullException if a non null field resolves to a null value
*/
protected CompletableFuture<Object> fetchField(ExecutionContext executionContext, ExecutionStrategyParameters parameters) {
Field field = parameters.getField().get(0);
GraphQLObjectType parentType = parameters.getTypeInfo().castType(GraphQLObjectType.class);
GraphQLFieldDefinition fieldDef = getFieldDef(executionContext.getGraphQLSchema(), parentType, field);
GraphqlFieldVisibility fieldVisibility = executionContext.getGraphQLSchema().getFieldVisibility();
Map<String, Object> argumentValues = valuesResolver.getArgumentValues(fieldVisibility, fieldDef.getArguments(), field.getArguments(), executionContext.getVariables());
GraphQLOutputType fieldType = fieldDef.getType();
DataFetchingFieldSelectionSet fieldCollector = DataFetchingFieldSelectionSetImpl.newCollector(executionContext, fieldType, parameters.getField());
ExecutionTypeInfo fieldTypeInfo = fieldTypeInfo(parameters, fieldDef);
DataFetchingEnvironment environment = newDataFetchingEnvironment(executionContext).source(parameters.getSource()).arguments(argumentValues).fieldDefinition(fieldDef).fields(parameters.getField()).fieldType(fieldType).fieldTypeInfo(fieldTypeInfo).parentType(parentType).selectionSet(fieldCollector).build();
Instrumentation instrumentation = executionContext.getInstrumentation();
InstrumentationFieldFetchParameters instrumentationFieldFetchParams = new InstrumentationFieldFetchParameters(executionContext, fieldDef, environment);
InstrumentationContext<Object> fetchCtx = instrumentation.beginFieldFetch(instrumentationFieldFetchParams);
CompletableFuture<Object> fetchedValue;
DataFetcher dataFetcher = fieldDef.getDataFetcher();
dataFetcher = instrumentation.instrumentDataFetcher(dataFetcher, instrumentationFieldFetchParams);
ExecutionId executionId = executionContext.getExecutionId();
try {
log.debug("'{}' fetching field '{}' using data fetcher '{}'...", executionId, fieldTypeInfo.getPath(), dataFetcher.getClass().getName());
Object fetchedValueRaw = dataFetcher.get(environment);
log.debug("'{}' field '{}' fetch returned '{}'", executionId, fieldTypeInfo.getPath(), fetchedValueRaw == null ? "null" : fetchedValueRaw.getClass().getName());
fetchedValue = Async.toCompletableFuture(fetchedValueRaw);
} catch (Exception e) {
log.debug(String.format("'%s', field '%s' fetch threw exception", executionId, fieldTypeInfo.getPath()), e);
fetchedValue = new CompletableFuture<>();
fetchedValue.completeExceptionally(e);
}
fetchCtx.onDispatched(fetchedValue);
return fetchedValue.handle((result, exception) -> {
fetchCtx.onCompleted(result, exception);
if (exception != null) {
handleFetchingException(executionContext, parameters, field, fieldDef, argumentValues, environment, exception);
return null;
} else {
return result;
}
}).thenApply(result -> unboxPossibleDataFetcherResult(executionContext, parameters, result)).thenApply(this::unboxPossibleOptional);
}
use of graphql.execution.instrumentation.Instrumentation in project graphql-java by graphql-java.
the class ExecutionStrategy method resolveField.
/**
* Called to fetch a value for a field and resolve it further in terms of the graphql query. This will call
* #fetchField followed by #completeField and the completed {@link ExecutionResult} is returned.
* <p>
* An execution strategy can iterate the fields to be executed and call this method for each one
* <p>
* Graphql fragments mean that for any give logical field can have one or more {@link Field} values associated with it
* in the query, hence the fieldList. However the first entry is representative of the field for most purposes.
*
* @param executionContext contains the top level execution parameters
* @param parameters contains the parameters holding the fields to be executed and source object
*
* @return an {@link ExecutionResult}
*
* @throws NonNullableFieldWasNullException if a non null field resolves to a null value
*/
protected CompletableFuture<ExecutionResult> resolveField(ExecutionContext executionContext, ExecutionStrategyParameters parameters) {
GraphQLFieldDefinition fieldDef = getFieldDef(executionContext, parameters, parameters.getField().get(0));
Instrumentation instrumentation = executionContext.getInstrumentation();
InstrumentationContext<ExecutionResult> fieldCtx = instrumentation.beginField(new InstrumentationFieldParameters(executionContext, fieldDef, fieldTypeInfo(parameters, fieldDef)));
CompletableFuture<ExecutionResult> result = fetchField(executionContext, parameters).thenCompose((fetchedValue) -> completeField(executionContext, parameters, fetchedValue));
fieldCtx.onDispatched(result);
result.whenComplete(fieldCtx::onCompleted);
return result;
}
use of graphql.execution.instrumentation.Instrumentation in project graphql-java by graphql-java.
the class GraphQL method executeAsync.
/**
* Executes the graphql query using the provided input object
* <p>
* This will return a promise (aka {@link CompletableFuture}) to provide a {@link ExecutionResult}
* which is the result of executing the provided query.
*
* @param executionInput {@link ExecutionInput}
*
* @return a promise to an {@link ExecutionResult} which can include errors
*/
public CompletableFuture<ExecutionResult> executeAsync(ExecutionInput executionInput) {
try {
log.debug("Executing request. operation name: '{}'. query: '{}'. variables '{}'", executionInput.getOperationName(), executionInput.getQuery(), executionInput.getVariables());
InstrumentationState instrumentationState = instrumentation.createState();
InstrumentationExecutionParameters inputInstrumentationParameters = new InstrumentationExecutionParameters(executionInput, this.graphQLSchema, instrumentationState);
executionInput = instrumentation.instrumentExecutionInput(executionInput, inputInstrumentationParameters);
InstrumentationExecutionParameters instrumentationParameters = new InstrumentationExecutionParameters(executionInput, this.graphQLSchema, instrumentationState);
InstrumentationContext<ExecutionResult> executionInstrumentation = instrumentation.beginExecution(instrumentationParameters);
GraphQLSchema graphQLSchema = instrumentation.instrumentSchema(this.graphQLSchema, instrumentationParameters);
CompletableFuture<ExecutionResult> executionResult = parseValidateAndExecute(executionInput, graphQLSchema, instrumentationState);
//
// finish up instrumentation
executionResult = executionResult.whenComplete(executionInstrumentation::onCompleted);
//
// allow instrumentation to tweak the result
executionResult = executionResult.thenCompose(result -> instrumentation.instrumentExecutionResult(result, instrumentationParameters));
return executionResult;
} catch (AbortExecutionException abortException) {
ExecutionResultImpl executionResult = new ExecutionResultImpl(abortException);
if (!abortException.getUnderlyingErrors().isEmpty()) {
executionResult = new ExecutionResultImpl(abortException.getUnderlyingErrors());
}
return CompletableFuture.completedFuture(executionResult);
}
}
use of graphql.execution.instrumentation.Instrumentation in project graphql-java by graphql-java.
the class BatchedExecutionStrategy method fetchData.
private CompletableFuture<FetchedValues> fetchData(ExecutionContext executionContext, ExecutionStrategyParameters parameters, String fieldName, ExecutionNode node, GraphQLFieldDefinition fieldDef) {
GraphQLObjectType parentType = node.getType();
List<Field> fields = node.getFields().get(fieldName);
List<MapOrList> parentResults = node.getParentResults();
GraphqlFieldVisibility fieldVisibility = executionContext.getGraphQLSchema().getFieldVisibility();
Map<String, Object> argumentValues = valuesResolver.getArgumentValues(fieldVisibility, fieldDef.getArguments(), fields.get(0).getArguments(), executionContext.getVariables());
GraphQLOutputType fieldType = fieldDef.getType();
DataFetchingFieldSelectionSet fieldCollector = DataFetchingFieldSelectionSetImpl.newCollector(executionContext, fieldType, fields);
DataFetchingEnvironment environment = newDataFetchingEnvironment(executionContext).source(node.getSources()).arguments(argumentValues).fieldDefinition(fieldDef).fields(fields).fieldType(fieldDef.getType()).fieldTypeInfo(parameters.getTypeInfo()).parentType(parentType).selectionSet(fieldCollector).build();
Instrumentation instrumentation = executionContext.getInstrumentation();
InstrumentationFieldFetchParameters instrumentationFieldFetchParameters = new InstrumentationFieldFetchParameters(executionContext, fieldDef, environment);
InstrumentationContext<Object> fetchCtx = instrumentation.beginFieldFetch(instrumentationFieldFetchParameters);
CompletableFuture<Object> fetchedValue;
try {
DataFetcher<?> dataFetcher = instrumentation.instrumentDataFetcher(getDataFetcher(fieldDef), instrumentationFieldFetchParameters);
Object fetchedValueRaw = dataFetcher.get(environment);
fetchedValue = Async.toCompletableFuture(fetchedValueRaw);
} catch (Exception e) {
fetchedValue = new CompletableFuture<>();
fetchedValue.completeExceptionally(e);
}
return fetchedValue.thenApply((result) -> assertResult(parentResults, result)).whenComplete(fetchCtx::onCompleted).handle(handleResult(executionContext, parameters, parentResults, fields, fieldDef, argumentValues, environment));
}
use of graphql.execution.instrumentation.Instrumentation in project graphql-java by graphql-java.
the class ExecutorServiceExecutionStrategy method execute.
@Override
public CompletableFuture<ExecutionResult> 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, parameters);
InstrumentationContext<ExecutionResult> executionStrategyCtx = instrumentation.beginExecutionStrategy(instrumentationParameters);
Map<String, List<Field>> fields = parameters.getFields();
Map<String, Future<CompletableFuture<ExecutionResult>>> futures = new LinkedHashMap<>();
for (String fieldName : fields.keySet()) {
final List<Field> currentField = fields.get(fieldName);
ExecutionPath fieldPath = parameters.getPath().segment(fieldName);
ExecutionStrategyParameters newParameters = parameters.transform(builder -> builder.field(currentField).path(fieldPath));
Callable<CompletableFuture<ExecutionResult>> resolveField = () -> resolveField(executionContext, newParameters);
futures.put(fieldName, executorService.submit(resolveField));
}
CompletableFuture<ExecutionResult> overallResult = new CompletableFuture<>();
executionStrategyCtx.onDispatched(overallResult);
try {
Map<String, Object> 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);
}
ExecutionResultImpl executionResult = new ExecutionResultImpl(results, executionContext.getErrors());
overallResult.complete(executionResult);
overallResult.whenComplete(executionStrategyCtx::onCompleted);
return overallResult;
} catch (InterruptedException | ExecutionException e) {
executionStrategyCtx.onCompleted(null, e);
throw new GraphQLException(e);
}
}
Aggregations