All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
graphql.kickstart.execution.instrumentation.AbstractTrackingApproach Maven / Gradle / Ivy
package graphql.kickstart.execution.instrumentation;
import graphql.ExecutionResult;
import graphql.execution.ExecutionId;
import graphql.execution.FieldValueInfo;
import graphql.execution.ResultPath;
import graphql.execution.instrumentation.ExecutionStrategyInstrumentationContext;
import graphql.execution.instrumentation.InstrumentationContext;
import graphql.execution.instrumentation.parameters.InstrumentationExecutionStrategyParameters;
import graphql.execution.instrumentation.parameters.InstrumentationFieldFetchParameters;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import lombok.extern.slf4j.Slf4j;
import org.dataloader.DataLoaderRegistry;
/** Handles logic common to tracking approaches. */
@Slf4j
public abstract class AbstractTrackingApproach implements TrackingApproach {
private final DataLoaderRegistry dataLoaderRegistry;
private final RequestStack stack = new RequestStack();
protected AbstractTrackingApproach(DataLoaderRegistry dataLoaderRegistry) {
this.dataLoaderRegistry = dataLoaderRegistry;
}
/** @return allows extending classes to modify the stack. */
protected RequestStack getStack() {
return stack;
}
@Override
public ExecutionStrategyInstrumentationContext beginExecutionStrategy(
InstrumentationExecutionStrategyParameters parameters) {
ExecutionId executionId = parameters.getExecutionContext().getExecutionId();
ResultPath path = parameters.getExecutionStrategyParameters().getPath();
int parentLevel = path.getLevel();
int curLevel = parentLevel + 1;
int fieldCount = parameters.getExecutionStrategyParameters().getFields().size();
synchronized (stack) {
stack.increaseExpectedFetchCount(executionId, curLevel, fieldCount);
stack.increaseHappenedStrategyCalls(executionId, curLevel);
}
return new ExecutionStrategyInstrumentationContext() {
@Override
public void onDispatched(CompletableFuture result) {
// default empty implementation
}
@Override
public void onCompleted(ExecutionResult result, Throwable t) {
// default empty implementation
}
@Override
public void onFieldValuesInfo(List fieldValueInfoList) {
synchronized (stack) {
stack.setStatus(
executionId,
handleOnFieldValuesInfo(fieldValueInfoList, stack, executionId, curLevel));
if (stack.allReady()) {
dispatchWithoutLocking();
}
}
}
};
}
//
// thread safety : called with synchronised(stack)
//
private boolean handleOnFieldValuesInfo(
List fieldValueInfoList,
RequestStack stack,
ExecutionId executionId,
int curLevel) {
stack.increaseHappenedOnFieldValueCalls(executionId, curLevel);
int expectedStrategyCalls = 0;
for (FieldValueInfo fieldValueInfo : fieldValueInfoList) {
if (fieldValueInfo.getCompleteValueType() == FieldValueInfo.CompleteValueType.OBJECT) {
expectedStrategyCalls++;
} else if (fieldValueInfo.getCompleteValueType() == FieldValueInfo.CompleteValueType.LIST) {
expectedStrategyCalls += getCountForList(fieldValueInfo);
}
}
stack.increaseExpectedStrategyCalls(executionId, curLevel + 1, expectedStrategyCalls);
return dispatchIfNeeded(stack, executionId, curLevel + 1);
}
private int getCountForList(FieldValueInfo fieldValueInfo) {
int result = 0;
for (FieldValueInfo cvi : fieldValueInfo.getFieldValueInfos()) {
if (cvi.getCompleteValueType() == FieldValueInfo.CompleteValueType.OBJECT) {
result++;
} else if (cvi.getCompleteValueType() == FieldValueInfo.CompleteValueType.LIST) {
result += getCountForList(cvi);
}
}
return result;
}
@Override
public InstrumentationContext beginFieldFetch(
InstrumentationFieldFetchParameters parameters) {
ExecutionId executionId = parameters.getExecutionContext().getExecutionId();
ResultPath path = parameters.getEnvironment().getExecutionStepInfo().getPath();
int level = path.getLevel();
return new InstrumentationContext() {
@Override
public void onDispatched(CompletableFuture result) {
synchronized (stack) {
stack.increaseFetchCount(executionId, level);
stack.setStatus(executionId, dispatchIfNeeded(stack, executionId, level));
if (stack.allReady()) {
dispatchWithoutLocking();
}
}
}
@Override
public void onCompleted(Object result, Throwable t) {
// default empty implementation
}
};
}
@Override
public void removeTracking(ExecutionId executionId) {
synchronized (stack) {
stack.removeExecution(executionId);
if (stack.allReady()) {
dispatchWithoutLocking();
}
}
}
//
// thread safety : called with synchronised(stack)
//
private boolean dispatchIfNeeded(RequestStack stack, ExecutionId executionId, int level) {
if (levelReady(stack, executionId, level)) {
return stack.dispatchIfNotDispatchedBefore(executionId, level);
}
return false;
}
//
// thread safety : called with synchronised(stack)
//
private boolean levelReady(RequestStack stack, ExecutionId executionId, int level) {
if (level == 1) {
// level 1 is special: there is only one strategy call and that's it
return stack.allFetchesHappened(executionId, 1);
}
return (levelReady(stack, executionId, level - 1)
&& stack.allOnFieldCallsHappened(executionId, level - 1)
&& stack.allStrategyCallsHappened(executionId, level)
&& stack.allFetchesHappened(executionId, level));
}
@Override
public void dispatch() {
synchronized (stack) {
dispatchWithoutLocking();
}
}
private void dispatchWithoutLocking() {
log.debug("Dispatching data loaders ({})", dataLoaderRegistry.getKeys());
dataLoaderRegistry.dispatchAll();
stack.allReset();
}
}