Skip to content

Commit

Permalink
Merge pull request #1543 from gentics/hotfix-1.10.x-sup-15904-2
Browse files Browse the repository at this point in the history
SUP-15409: Speed up parent loading the right way
  • Loading branch information
npomaroli authored Oct 13, 2023
2 parents 2c53141 + d057127 commit a5480eb
Show file tree
Hide file tree
Showing 8 changed files with 305 additions and 50 deletions.
5 changes: 5 additions & 0 deletions LTS-CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ include::content/docs/variables.adoc-include[]
The LTS changelog lists releases which are only accessible via a commercial subscription.
All fixes and changes in LTS releases will be released the next minor release. Changes from LTS 1.4.x will be included in release 1.5.0.

[[v1.10.17]]
== 1.10.17 (TBD)

icon:check[] GraphQL: Parent loading has been speeded up by using a batch data loading.

[[v1.10.16]]
== 1.10.16 (04.10.2023)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,11 +249,12 @@ default String getPathSegment(HibNode node, String branchUuid, ContainerType typ

/**
* Return a map with node as a key and all its field containers as values, filtering for the provided parameters.
* This method does not check permission
* @param nodes
* @param branchUuid
* @param type
* @return
* This method does not check permission.
* @implNote This method may or may not return nodes, that do not have any field containers.
* @param nodes set of nodes
* @param branchUuid branch UUID
* @param type container type for filtering containers
* @return map of nodes to lists of field containers
*/
Map<HibNode, List<HibNodeFieldContainer>> getFieldsContainers(Set<HibNode> nodes, String branchUuid, ContainerType type);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,10 @@ public interface NodeDao extends Dao<HibNode>, DaoTransformable<HibNode, NodeRes
HibNode getParentNode(HibNode node, String branchUuid);

/**
* Returns a map with nodes and their immediate parents
* @param nodes
* @param branchUuid
* @return
* Returns a map with nodes and their immediate parents. Nodes, which do not have a parent will be mapped to null.
* @param nodes collection of nodes (must not be null or contain null values)
* @param branchUuid branch UUID
* @return map of parents per node
*/
Map<HibNode, HibNode> getParentNodes(Collection<HibNode> nodes, String branchUuid);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import static com.gentics.mesh.core.rest.common.ContainerType.PUBLISHED;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -120,9 +121,9 @@ public HibNode getParentNode(HibNode node, String branchUuid) {

@Override
public Map<HibNode, HibNode> getParentNodes(Collection<HibNode> nodes, String branchUuid) {
return nodes.stream()
.map(node -> Pair.of(node, getParentNode(node, branchUuid)))
.collect(Collectors.toMap(Pair::getKey, Pair::getValue));
Map<HibNode, HibNode> ret = new HashMap<>();
nodes.forEach(node -> ret.put(node, getParentNode(node, branchUuid)));
return ret;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ public void handleQuery(GraphQLContext gc, String body) {
dataLoaderRegistry.register(NodeDataLoader.CONTENT_LOADER_KEY, DataLoader.newDataLoader(NodeDataLoader.CONTENT_LOADER, options));
dataLoaderRegistry.register(NodeDataLoader.CHILDREN_LOADER_KEY, DataLoader.newDataLoader(NodeDataLoader.CHILDREN_LOADER, options));
dataLoaderRegistry.register(NodeDataLoader.PATH_LOADER_KEY, DataLoader.newDataLoader(NodeDataLoader.PATH_LOADER, options));
dataLoaderRegistry.register(NodeDataLoader.PARENT_LOADER_KEY, DataLoader.newDataLoader(NodeDataLoader.PARENT_LOADER, options));
dataLoaderRegistry.register(NodeDataLoader.BREADCRUMB_LOADER_KEY, DataLoader.newDataLoader(NodeDataLoader.BREADCRUMB_LOADER, options));
dataLoaderRegistry.register(FieldDefinitionProvider.LINK_REPLACER_DATA_LOADER_KEY, DataLoader.newDataLoader(typeProvider.getFieldDefProvider().LINK_REPLACER_LOADER, options));
dataLoaderRegistry.register(FieldDefinitionProvider.BOOLEAN_LIST_VALUES_DATA_LOADER_KEY, DataLoader.newDataLoader(typeProvider.getFieldDefProvider().BOOLEAN_LIST_VALUE_LOADER, options));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package com.gentics.mesh.graphql.dataloader;

import org.dataloader.DataLoader;

import com.gentics.mesh.core.data.node.NodeContent;

import graphql.ExceptionWhileDataFetching;
import graphql.execution.DataFetcherResult;
import graphql.execution.DataFetcherResult.Builder;
import graphql.schema.DataFetchingEnvironment;

/**
* Container class for an instance of {@link NodeContent} and an optional {@link RuntimeException}.
* Instances of this class can be returned from {@link DataLoader} implementations (like the e.g. {@link NodeDataLoader#PARENT_LOADER}).
*/
public class NodeContentWithOptionalRuntimeException {
/**
* NodeContent to be returned (may be null)
*/
private final NodeContent nodeContent;

/**
* RuntimeException, which was thrown while trying to fetch the nodeContent (may be null)
*/
private final RuntimeException runtimeException;

/**
* Empty instance (nodeContent and runtimeException are both null). Can be used to return null but without error
*/
public final static NodeContentWithOptionalRuntimeException EMPTY = new NodeContentWithOptionalRuntimeException();

/**
* Constructor for empty instance
*/
private NodeContentWithOptionalRuntimeException() {
this(null, null);
}

/**
* Create instance returning the given nodeContent
* @param nodeContent returned value
*/
public NodeContentWithOptionalRuntimeException(NodeContent nodeContent) {
this(nodeContent, null);
}

/**
* Create instance returning null and adding an error
* @param runtimeException exception
*/
public NodeContentWithOptionalRuntimeException(RuntimeException runtimeException) {
this(null, runtimeException);
}

/**
* Create instance returning a nodeContent (may be null) and optionally adding an error
* @param nodeContent returned value
* @param runtimeException optional exception
*/
public NodeContentWithOptionalRuntimeException(NodeContent nodeContent, RuntimeException runtimeException) {
this.nodeContent = nodeContent;
this.runtimeException = runtimeException;
}

/**
* Transform the value into an instance of {@link DataFetcherResult} for the given environment.
* If the nodeContent is null, but a runtimeException has been set, the runtimeException will be thrown
* @param env data fetching environment
* @return data fetcher result
*/
public DataFetcherResult<NodeContent> getResult(DataFetchingEnvironment env) {
if (nodeContent == null && runtimeException != null) {
throw runtimeException;
}
Builder<NodeContent> builder = DataFetcherResult.<NodeContent>newResult().data(nodeContent);
if (runtimeException != null) {
builder.error(new ExceptionWhileDataFetching(env.getExecutionStepInfo().getPath(), runtimeException, env.getField().getSourceLocation()));
}
return builder.build();
}
}
Loading

0 comments on commit a5480eb

Please sign in to comment.