Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gh-3292: REST API Gremlin Timeout and Execute Endpoints #3294

Merged
merged 12 commits into from
Sep 19, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
package uk.gov.gchq.gaffer.tinkerpop.util.modern;

import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;

import uk.gov.gchq.gaffer.commonutil.pair.Pair;
import uk.gov.gchq.gaffer.data.element.Entity;
import uk.gov.gchq.gaffer.tinkerpop.GafferPopGraph;
import uk.gov.gchq.gaffer.tinkerpop.generator.GafferPopVertexGenerator;

import static uk.gov.gchq.gaffer.tinkerpop.util.modern.GafferPopModernTestUtils.AGE;
import static uk.gov.gchq.gaffer.tinkerpop.util.modern.GafferPopModernTestUtils.NAME;
Expand Down Expand Up @@ -163,4 +166,8 @@ public Entity toEntity() {
.property(AGE, age)
.build();
}

public Vertex toVertex(GafferPopGraph graph) {
return new GafferPopVertexGenerator(graph)._apply(toEntity());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

package uk.gov.gchq.gaffer.rest.config;

import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.builder.fluent.Configurations;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
Expand All @@ -31,28 +31,54 @@

@Configuration
public class GremlinConfig {

private static final Logger LOGGER = LoggerFactory.getLogger(GremlinConfig.class);

/**
* Default path to look for a GafferPop properties file if not defined in the store properties.
*/
private static final String DEFAULT_PROPERTIES = "/gaffer/gafferpop.properties";

/**
* Default timeout for executing gremlin queries (2 min).
*/
private static final Long DEFAULT_REQUEST_TIMEOUT = 120000L;

/**
* Key for GafferPop properties file to specify the timeout on gremlin queries to the REST API.
*/
private static final String REQUEST_TIMEOUT_KEY = "gaffer.rest.timeout";

@Bean
public GraphTraversalSource graphTraversalSource(final GraphFactory graphFactory) throws Exception {
// Determine where to look for the GafferPop properties
String gafferPopProperties = graphFactory.getGraph().getStoreProperties().get(GafferPopGraph.GAFFERPOP_PROPERTIES);
if (gafferPopProperties == null) {
LOGGER.warn("GafferPop properties file was not specified. Using default location: {}", DEFAULT_PROPERTIES);
gafferPopProperties = DEFAULT_PROPERTIES;
}
public GraphTraversalSource graphTraversalSource(final GraphFactory graphFactory) {
// Obtain the graph traversal
try (Graph graph = GafferPopGraph.open(new Configurations().properties(gafferPopProperties), graphFactory.getGraph())) {
return graph.traversal();
Graph graph = GafferPopGraph.open(findPropertiesFile(graphFactory), graphFactory.getGraph());
return graph.traversal();
}

@Bean
public Long requestTimeout(final GraphFactory graphFactory) {
return findPropertiesFile(graphFactory).getLong(REQUEST_TIMEOUT_KEY, DEFAULT_REQUEST_TIMEOUT);
}

/**
* Finds and loads the correct config file for gafferpop.
*
* @param graphFactory The graph factory.
* @return Loaded properties from file.
* @throws ConfigurationException If problem loading.
*/
private PropertiesConfiguration findPropertiesFile(final GraphFactory graphFactory) {
try {
// Determine where to look for the GafferPop properties
String gafferPopProperties = graphFactory.getGraph().getStoreProperties().get(GafferPopGraph.GAFFERPOP_PROPERTIES);
if (gafferPopProperties == null) {
LOGGER.warn("GafferPop properties file was not specified. Using default location: {}", DEFAULT_PROPERTIES);
gafferPopProperties = DEFAULT_PROPERTIES;
}
return new Configurations().properties(gafferPopProperties);
} catch (final ConfigurationException e) {
LOGGER.error("Error loading GafferPop config, Gremlin will be unavailable: {}", e.getMessage());
return EmptyGraph.instance().traversal();
LOGGER.warn("Using default values for GafferPop, failed to load a GafferPop config: {}", e.getMessage());
return new PropertiesConfiguration();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,18 @@ public class GremlinWebSocketConfig implements WebSocketConfigurer {

private final GraphTraversalSource g;
private final AbstractUserFactory userFactory;
private final Long requestTimeout;

@Autowired
public GremlinWebSocketConfig(final GraphTraversalSource g, final AbstractUserFactory userFactory) {
public GremlinWebSocketConfig(final GraphTraversalSource g, final AbstractUserFactory userFactory, final Long requestTimeout) {
this.g = g;
this.userFactory = userFactory;
this.requestTimeout = requestTimeout;
}

@Override
public void registerWebSocketHandlers(final WebSocketHandlerRegistry registry) {
registry.addHandler(new GremlinWebSocketHandler(g, userFactory), "/gremlin");
registry.addHandler(new GremlinWebSocketHandler(g, userFactory, requestTimeout), "/gremlin");
}

}
Loading
Loading