/** * When this is called the deferred execution will begin * * @return the publisher of deferred results */ public Publisher<ExecutionResult> startDeferredCalls() { drainDeferredCalls(); return publisher; } }
@SuppressWarnings("FutureReturnValueIgnored") private void drainDeferredCalls() { if (deferredCalls.isEmpty()) { publisher.noMoreData(); return; } DeferredCall deferredCall = deferredCalls.pop(); CompletableFuture<ExecutionResult> future = deferredCall.invoke(); future.whenComplete((executionResult, exception) -> { if (exception != null) { publisher.offerError(exception); return; } publisher.offer(executionResult); drainDeferredCalls(); }); }
private CompletableFuture<ExecutionResult> deferSupport(ExecutionContext executionContext, CompletableFuture<ExecutionResult> result) { return result.thenApply(er -> { DeferSupport deferSupport = executionContext.getDeferSupport(); if (deferSupport.isDeferDetected()) { // we start the rest of the query now to maximize throughput. We have the initial important results // and now we can start the rest of the calls as early as possible (even before some one subscribes) Publisher<ExecutionResult> publisher = deferSupport.startDeferredCalls(); return ExecutionResultImpl.newExecutionResult().from((ExecutionResultImpl) er) .addExtension(GraphQL.DEFERRED_RESULTS, publisher) .build(); } return er; }); }
private boolean isDeferred(ExecutionContext executionContext, ExecutionStrategyParameters parameters, MergedField currentField) { DeferSupport deferSupport = executionContext.getDeferSupport(); if (deferSupport.checkForDeferDirective(currentField)) { DeferredErrorSupport errorSupport = new DeferredErrorSupport(); // with a deferred field we are really resetting where we execute from, that is from this current field onwards Map<String, MergedField> fields = new LinkedHashMap<>(); fields.put(currentField.getName(), currentField); ExecutionStrategyParameters callParameters = parameters.transform(builder -> { MergedSelectionSet mergedSelectionSet = newMergedSelectionSet().subFields(fields).build(); builder.deferredErrorSupport(errorSupport) .field(currentField) .fields(mergedSelectionSet) .parent(null) // this is a break in the parent -> child chain - its a new start effectively .listSize(0) .currentListIndex(0); } ); DeferredCall call = new DeferredCall(deferredExecutionResult(executionContext, callParameters), errorSupport); deferSupport.enqueue(call); return true; } return false; }
@SuppressWarnings("SameReturnValue") private Object handleCoercionProblem(ExecutionContext context, ExecutionStrategyParameters parameters, CoercingSerializeException e) { SerializationError error = new SerializationError(parameters.getPath(), e); log.warn(error.getMessage(), e); context.addError(error); parameters.deferredErrorSupport().onError(error); return null; }
private ExecutionResult addErrorsEncountered(ExecutionResult executionResult) { List<GraphQLError> errorsEncountered = errorSupport.getErrors(); if (errorsEncountered.isEmpty()) { return executionResult; } ExecutionResultImpl sourceResult = (ExecutionResultImpl) executionResult; ExecutionResultImpl.Builder builder = ExecutionResultImpl.newExecutionResult().from(sourceResult); builder.addErrors(errorsEncountered); return builder.build(); }
private void handleFetchingException(ExecutionContext executionContext, ExecutionStrategyParameters parameters, DataFetchingEnvironment environment, Throwable e) { DataFetcherExceptionHandlerParameters handlerParameters = DataFetcherExceptionHandlerParameters.newExceptionParameters() .dataFetchingEnvironment(environment) .exception(e) .build(); DataFetcherExceptionHandlerResult handlerResult = dataFetcherExceptionHandler.onException(handlerParameters); handlerResult.getErrors().forEach(executionContext::addError); parameters.deferredErrorSupport().onFetchingException(parameters, e); }
private boolean isDeferred(ExecutionContext executionContext, ExecutionStrategyParameters parameters, MergedField currentField) { DeferSupport deferSupport = executionContext.getDeferSupport(); if (deferSupport.checkForDeferDirective(currentField)) { DeferredErrorSupport errorSupport = new DeferredErrorSupport(); // with a deferred field we are really resetting where we execute from, that is from this current field onwards Map<String, MergedField> fields = new LinkedHashMap<>(); fields.put(currentField.getName(), currentField); ExecutionStrategyParameters callParameters = parameters.transform(builder -> { MergedSelectionSet mergedSelectionSet = newMergedSelectionSet().subFields(fields).build(); builder.deferredErrorSupport(errorSupport) .field(currentField) .fields(mergedSelectionSet) .parent(null) // this is a break in the parent -> child chain - its a new start effectively .listSize(0) .currentListIndex(0); } ); DeferredCall call = new DeferredCall(deferredExecutionResult(executionContext, callParameters), errorSupport); deferSupport.enqueue(call); return true; } return false; }
@SuppressWarnings("FutureReturnValueIgnored") private void drainDeferredCalls() { if (deferredCalls.isEmpty()) { publisher.noMoreData(); return; } DeferredCall deferredCall = deferredCalls.pop(); CompletableFuture<ExecutionResult> future = deferredCall.invoke(); future.whenComplete((executionResult, exception) -> { if (exception != null) { publisher.offerError(exception); return; } publisher.offer(executionResult); drainDeferredCalls(); }); }
private void handleUnresolvedTypeProblem(ExecutionContext context, ExecutionStrategyParameters parameters, UnresolvedTypeException e) { UnresolvedTypeError error = new UnresolvedTypeError(parameters.getPath(), parameters.getExecutionStepInfo(), e); log.warn(error.getMessage(), e); context.addError(error); parameters.deferredErrorSupport().onError(error); }
private CompletableFuture<ExecutionResult> deferSupport(ExecutionContext executionContext, CompletableFuture<ExecutionResult> result) { return result.thenApply(er -> { DeferSupport deferSupport = executionContext.getDeferSupport(); if (deferSupport.isDeferDetected()) { // we start the rest of the query now to maximize throughput. We have the initial important results // and now we can start the rest of the calls as early as possible (even before some one subscribes) Publisher<ExecutionResult> publisher = deferSupport.startDeferredCalls(); return ExecutionResultImpl.newExecutionResult().from((ExecutionResultImpl) er) .addExtension(GraphQL.DEFERRED_RESULTS, publisher) .build(); } return er; }); }
/** * When this is called the deferred execution will begin * * @return the publisher of deferred results */ public Publisher<ExecutionResult> startDeferredCalls() { drainDeferredCalls(); return publisher; } }
private ExecutionResult addErrorsEncountered(ExecutionResult executionResult) { List<GraphQLError> errorsEncountered = errorSupport.getErrors(); if (errorsEncountered.isEmpty()) { return executionResult; } ExecutionResultImpl sourceResult = (ExecutionResultImpl) executionResult; ExecutionResultImpl.Builder builder = ExecutionResultImpl.newExecutionResult().from(sourceResult); builder.addErrors(errorsEncountered); return builder.build(); }
private void handleFetchingException(ExecutionContext executionContext, ExecutionStrategyParameters parameters, DataFetchingEnvironment environment, Throwable e) { DataFetcherExceptionHandlerParameters handlerParameters = DataFetcherExceptionHandlerParameters.newExceptionParameters() .dataFetchingEnvironment(environment) .exception(e) .build(); DataFetcherExceptionHandlerResult handlerResult = dataFetcherExceptionHandler.onException(handlerParameters); handlerResult.getErrors().forEach(executionContext::addError); parameters.deferredErrorSupport().onFetchingException(parameters, e); }
private void handleTypeMismatchProblem(ExecutionContext context, ExecutionStrategyParameters parameters, Object result) { TypeMismatchError error = new TypeMismatchError(parameters.getPath(), parameters.getExecutionStepInfo().getUnwrappedNonNullType()); log.warn("{} got {}", error.getMessage(), result.getClass()); context.addError(error); parameters.deferredErrorSupport().onError(error); }
public void onFetchingException(ExecutionStrategyParameters parameters, Throwable e) { ExceptionWhileDataFetching error = new ExceptionWhileDataFetching(parameters.getPath(), e, parameters.getField().getSingleField().getSourceLocation()); onError(error); }
@SuppressWarnings("SameReturnValue") private Object handleCoercionProblem(ExecutionContext context, ExecutionStrategyParameters parameters, CoercingSerializeException e) { SerializationError error = new SerializationError(parameters.getPath(), e); log.warn(error.getMessage(), e); context.addError(error); parameters.deferredErrorSupport().onError(error); return null; }
private void handleUnresolvedTypeProblem(ExecutionContext context, ExecutionStrategyParameters parameters, UnresolvedTypeException e) { UnresolvedTypeError error = new UnresolvedTypeError(parameters.getPath(), parameters.getExecutionStepInfo(), e); log.warn(error.getMessage(), e); context.addError(error); parameters.deferredErrorSupport().onError(error); }
private void handleTypeMismatchProblem(ExecutionContext context, ExecutionStrategyParameters parameters, Object result) { TypeMismatchError error = new TypeMismatchError(parameters.getPath(), parameters.getExecutionStepInfo().getUnwrappedNonNullType()); log.warn("{} got {}", error.getMessage(), result.getClass()); context.addError(error); parameters.deferredErrorSupport().onError(error); }
public void onFetchingException(ExecutionStrategyParameters parameters, Throwable e) { ExceptionWhileDataFetching error = new ExceptionWhileDataFetching(parameters.getPath(), e, parameters.getField().getSingleField().getSourceLocation()); onError(error); }