Skip to content

Commit af71310

Browse files
sazzad16gkorland
andauthored
Support query timeout (#98)
* Support query timeout * snapshot repo Co-authored-by: Guy Korland <[email protected]>
1 parent aa79464 commit af71310

File tree

10 files changed

+185
-21
lines changed

10 files changed

+185
-21
lines changed

pom.xml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,18 @@
4747
</license>
4848
</licenses>
4949

50+
<!-- temporarily adding jedis snapshot repository -->
51+
<repositories>
52+
<repository>
53+
<id>snapshots-repo</id>
54+
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
55+
</repository>
56+
</repositories>
5057
<dependencies>
5158
<dependency>
5259
<groupId>redis.clients</groupId>
5360
<artifactId>jedis</artifactId>
54-
<version>3.4.1</version>
61+
<version>3.5.0-SNAPSHOT</version>
5562
</dependency>
5663
<dependency>
5764
<groupId>org.apache.commons</groupId>

src/main/java/com/redislabs/redisgraph/RedisGraph.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ public interface RedisGraph extends Closeable {
1414
*/
1515
ResultSet query(String graphId, String query);
1616

17+
/**
18+
* Execute a Cypher query with timeout.
19+
* @param graphId a graph to perform the query on
20+
* @param query Cypher query
21+
* @param timeout
22+
* @return a result set
23+
*/
24+
ResultSet query(String graphId, String query, long timeout);
1725

1826
/**
1927
* Execute a Cypher query with arguments
@@ -35,6 +43,16 @@ public interface RedisGraph extends Closeable {
3543
*/
3644
ResultSet query(String graphId, String query, Map<String, Object> params);
3745

46+
/**
47+
* Executes a cypher query with parameters and timeout.
48+
* @param graphId a graph to perform the query on.
49+
* @param query Cypher query.
50+
* @param params parameters map.
51+
* @param timeout
52+
* @return a result set.
53+
*/
54+
ResultSet query(String graphId, String query, Map<String, Object> params, long timeout);
55+
3856
/**
3957
* Invokes stored procedures without arguments
4058
* @param graphId a graph to perform the query on

src/main/java/com/redislabs/redisgraph/RedisGraphTransaction.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public interface RedisGraphTransaction extends
2222
MultiKeyCommandsPipeline, ClusterPipeline,
2323
BinaryScriptingCommandsPipeline, ScriptingCommandsPipeline,
2424
BasicRedisPipeline, BinaryRedisPipeline, RedisPipeline, Closeable {
25+
2526
/**
2627
* Execute a Cypher query.
2728
* @param graphId a graph to perform the query on
@@ -30,6 +31,15 @@ public interface RedisGraphTransaction extends
3031
*/
3132
Response<ResultSet> query(String graphId, String query);
3233

34+
/**
35+
* Execute a Cypher query with timeout.
36+
* @param graphId a graph to perform the query on
37+
* @param query Cypher query
38+
* @param timeout
39+
* @return a response which builds the result set with the query answer.
40+
*/
41+
Response<ResultSet> query(String graphId, String query, long timeout);
42+
3343
/**
3444
* Execute a Cypher query with arguments
3545
* @param graphId a graph to perform the query on
@@ -50,6 +60,16 @@ public interface RedisGraphTransaction extends
5060
*/
5161
Response<ResultSet> query(String graphId, String query, Map<String, Object> params);
5262

63+
/**
64+
* Executes a cypher query with parameters and timeout.
65+
* @param graphId a graph to perform the query on.
66+
* @param query Cypher query.
67+
* @param params parameters map.
68+
* @param timeout
69+
* @return a response which builds the result set with the query answer.
70+
*/
71+
Response<ResultSet> query(String graphId, String query, Map<String, Object> params, long timeout);
72+
5373
/**
5474
* Invokes stored procedures without arguments
5575
* @param graphId a graph to perform the query on

src/main/java/com/redislabs/redisgraph/impl/Utils.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public class Utils {
1414
public static final List<String> DUMMY_LIST = new ArrayList<>(0);
1515
public static final Map<String, List<String>> DUMMY_MAP = new HashMap<>(0);
1616
public static final String COMPACT_STRING = "--COMPACT";
17+
public static final String TIMEOUT_STRING = "TIMEOUT";
1718

1819
private static final CharSequenceTranslator ESCAPE_CHYPER;
1920
static {

src/main/java/com/redislabs/redisgraph/impl/api/AbstractRedisGraph.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@ public abstract class AbstractRedisGraph implements RedisGraph {
2727
*/
2828
protected abstract ResultSet sendQuery(String graphId, String preparedQuery);
2929

30+
/**
31+
* Sends a query to the redis graph.Implementation and context dependent
32+
* @param graphId graph to be queried
33+
* @param preparedQuery prepared query
34+
* @param timeout
35+
* @return Result set
36+
*/
37+
protected abstract ResultSet sendQuery(String graphId, String preparedQuery, long timeout);
38+
3039
/**
3140
* Execute a Cypher query.
3241
* @param graphId a graph to perform the query on
@@ -37,6 +46,18 @@ public ResultSet query(String graphId, String query) {
3746
return sendQuery(graphId, query);
3847
}
3948

49+
/**
50+
* Execute a Cypher query with timeout.
51+
* @param graphId a graph to perform the query on
52+
* @param timeout
53+
* @param query Cypher query
54+
* @return a result set
55+
*/
56+
@Override
57+
public ResultSet query(String graphId, String query, long timeout) {
58+
return sendQuery(graphId, query, timeout);
59+
}
60+
4061
/**
4162
* Execute a Cypher query with arguments
4263
* @param graphId a graph to perform the query on
@@ -63,6 +84,19 @@ public ResultSet query(String graphId, String query, Map<String, Object> params)
6384
return sendQuery(graphId, preparedQuery);
6485
}
6586

87+
/**
88+
* Executes a cypher query with parameters and timeout.
89+
* @param graphId a graph to perform the query on.
90+
* @param timeout
91+
* @param query Cypher query.
92+
* @param params parameters map.
93+
* @return a result set.
94+
*/
95+
@Override
96+
public ResultSet query(String graphId, String query, Map<String, Object> params, long timeout) {
97+
String preparedQuery = Utils.prepareQuery(query, params);
98+
return sendQuery(graphId, preparedQuery, timeout);
99+
}
66100

67101
public ResultSet callProcedure(String graphId, String procedure){
68102
return callProcedure(graphId, procedure, Utils.DUMMY_LIST, Utils.DUMMY_MAP);

src/main/java/com/redislabs/redisgraph/impl/api/ContextedRedisGraph.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,29 @@ protected ResultSet sendQuery(String graphId, String preparedQuery) {
6060
}
6161
}
6262

63+
/**
64+
* Sends the query over the instance only connection
65+
* @param graphId graph to be queried
66+
* @param timeout
67+
* @param preparedQuery prepared query
68+
* @return Result set with the query answer
69+
*/
70+
@Override
71+
protected ResultSet sendQuery(String graphId, String preparedQuery, long timeout) {
72+
Jedis conn = getConnection();
73+
try {
74+
List<Object> rawResponse = (List<Object>) conn.sendBlockingCommand(RedisGraphCommand.QUERY,
75+
graphId, preparedQuery, Utils.COMPACT_STRING, Utils.TIMEOUT_STRING, Long.toString(timeout));
76+
return new ResultSetImpl(rawResponse, this, caches.getGraphCache(graphId));
77+
}
78+
catch (JRedisGraphRunTimeException rt) {
79+
throw rt;
80+
}
81+
catch (JedisDataException j) {
82+
throw new JRedisGraphCompileTimeException(j);
83+
}
84+
}
85+
6386
/**
6487
* @return Returns the instance Jedis connection.
6588
*/

src/main/java/com/redislabs/redisgraph/impl/api/RedisGraph.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,21 @@ protected ResultSet sendQuery(String graphId, String preparedQuery){
6969
}
7070
}
7171

72+
/**
73+
* Overrides the abstract function.
74+
* Sends the query from any Jedis connection received from the Jedis pool and closes it once done
75+
* @param graphId graph to be queried
76+
* @param preparedQuery prepared query
77+
* @param timeout
78+
* @return Result set with the query answer
79+
*/
80+
@Override
81+
protected ResultSet sendQuery(String graphId, String preparedQuery, long timeout){
82+
try (ContextedRedisGraph contextedRedisGraph = new ContextedRedisGraph(getConnection())) {
83+
contextedRedisGraph.setRedisGraphCaches(caches);
84+
return contextedRedisGraph.sendQuery(graphId, preparedQuery, timeout);
85+
}
86+
}
7287

7388
/**
7489
* Closes the Jedis pool

src/main/java/com/redislabs/redisgraph/impl/api/RedisGraphTransaction.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,26 @@ public ResultSet build(Object o) {
4747
});
4848
}
4949

50+
/**
51+
* Execute a Cypher query with timeout.
52+
*
53+
* NOTE: timeout is simply sent to DB. Socket timeout will not be changed.
54+
* @param graphId a graph to perform the query on
55+
* @param query Cypher query
56+
* @param timeout
57+
* @return a response which builds the result set with the query answer.
58+
*/
59+
@Override
60+
public Response<ResultSet> query(String graphId, String query, long timeout) {
61+
client.sendCommand(RedisGraphCommand.QUERY, graphId, query, "--COMPACT", "TIMEOUT", Long.toString(timeout));
62+
return getResponse(new Builder<ResultSet>() {
63+
@Override
64+
public ResultSet build(Object o) {
65+
return new ResultSetImpl((List<Object>)o, redisGraph, caches.getGraphCache(graphId));
66+
}
67+
});
68+
}
69+
5070
/**
5171
* Execute a Cypher query with arguments
5272
*
@@ -88,6 +108,28 @@ public ResultSet build(Object o) {
88108
});
89109
}
90110

111+
/**
112+
* Executes a cypher query with parameters and timeout.
113+
*
114+
* NOTE: timeout is simply sent to DB. Socket timeout will not be changed.
115+
* timeout.
116+
* @param graphId a graph to perform the query on.
117+
* @param query Cypher query.
118+
* @param params parameters map.
119+
* @param timeout
120+
* @return a response which builds the result set with the query answer.
121+
*/
122+
@Override
123+
public Response<ResultSet> query(String graphId, String query, Map<String, Object> params, long timeout) {
124+
String preparedQuery = Utils.prepareQuery(query, params);
125+
client.sendCommand(RedisGraphCommand.QUERY, graphId, preparedQuery, "--COMPACT", "TIMEOUT", Long.toString(timeout));
126+
return getResponse(new Builder<ResultSet>() {
127+
@Override
128+
public ResultSet build(Object o) {
129+
return new ResultSetImpl((List<Object>)o, redisGraph, caches.getGraphCache(graphId));
130+
}
131+
});
132+
}
91133

92134
/**
93135
* Invokes stored procedures without arguments, in multi/exec context

src/test/java/com/redislabs/redisgraph/RedisGraphAPITest.java

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
11
package com.redislabs.redisgraph;
22

3-
4-
import java.util.*;
5-
import java.util.stream.Collectors;
6-
import java.util.stream.IntStream;
7-
3+
import com.redislabs.redisgraph.Statistics.Label;
84
import com.redislabs.redisgraph.graph_entities.Edge;
95
import com.redislabs.redisgraph.graph_entities.Node;
106
import com.redislabs.redisgraph.graph_entities.Path;
117
import com.redislabs.redisgraph.graph_entities.Property;
128
import com.redislabs.redisgraph.impl.api.RedisGraph;
9+
import com.redislabs.redisgraph.impl.resultset.RecordImpl;
1310
import com.redislabs.redisgraph.impl.resultset.ResultSetImpl;
1411
import com.redislabs.redisgraph.test.utils.PathBuilder;
15-
import org.junit.*;
12+
import redis.clients.jedis.exceptions.JedisDataException;
1613

17-
import com.redislabs.redisgraph.Statistics.Label;
18-
19-
import static com.redislabs.redisgraph.Header.ResultSetColumnTypes.*;
14+
import java.util.*;
15+
import java.util.stream.Collectors;
16+
import java.util.stream.IntStream;
17+
import org.junit.*;
2018

2119
public class RedisGraphAPITest {
2220

@@ -29,20 +27,18 @@ public RedisGraphAPITest() {
2927
public void createApi(){
3028
api = new RedisGraph();
3129
}
30+
3231
@After
3332
public void deleteGraph() {
34-
3533
api.deleteGraph("social");
3634
api.close();
3735
}
3836

39-
4037
@Test
4138
public void testCreateNode() {
4239
// Create a node
4340
ResultSet resultSet = api.query("social", "CREATE ({name:'roi',age:32})");
4441

45-
4642
Assert.assertEquals(1, resultSet.getStatistics().nodesCreated());
4743
Assert.assertNull(resultSet.getStatistics().getStringValue(Label.NODES_DELETED));
4844
Assert.assertNull(resultSet.getStatistics().getStringValue(Label.RELATIONSHIPS_CREATED));
@@ -116,8 +112,6 @@ public void testDeleteNodes(){
116112

117113
Assert.assertNotNull(deleteResult.getStatistics().getStringValue(Label.QUERY_INTERNAL_EXECUTION_TIME));
118114

119-
120-
121115
}
122116

123117
@Test
@@ -192,7 +186,6 @@ public void testHeader(){
192186
Assert.assertEquals("r", schemaNames.get(1));
193187
Assert.assertEquals("a.age", schemaNames.get(2));
194188

195-
196189
}
197190

198191
@Test
@@ -311,7 +304,6 @@ public void testRecord(){
311304

312305
}
313306

314-
315307
@Ignore
316308
@Test
317309
public void tinyTestMultiThread(){
@@ -322,9 +314,7 @@ public void tinyTestMultiThread(){
322314
mapToObj(
323315
j-> api.query("social", "MATCH (a:person) RETURN a")).
324316
collect(Collectors.toList());
325-
326317
}
327-
328318
}
329319

330320
@Test
@@ -484,15 +474,13 @@ record = resultSet.next();
484474

485475
}
486476

487-
488477
@Test
489478
public void testEscapedQuery() {
490479
Assert.assertNotNull(api.query("social", "CREATE (:escaped{s1:%s,s2:%s})", "S\"'", "S'\""));
491480
Assert.assertNotNull(api.query("social", "MATCH (n) where n.s1=%s and n.s2=%s RETURN n", "S\"'", "S'\""));
492481
Assert.assertNotNull(api.query("social", "MATCH (n) where n.s1='S\"' RETURN n"));
493482
}
494483

495-
496484
@Test
497485
public void testMultiExec(){
498486
try (RedisGraphContext c = api.getContext()) {
@@ -965,4 +953,12 @@ public void testCachedExecution() {
965953
Assert.assertEquals(params.get("val"), r.getValue(0));
966954
Assert.assertTrue(resultSet.getStatistics().cachedExecution());
967955
}
956+
957+
@Test
958+
public void timeoutArgument() {
959+
ResultSet rs = api.query("social", "UNWIND range(0,100) AS x WITH x AS x WHERE x = 100 RETURN x", 1L);
960+
Assert.assertEquals(1, rs.size());
961+
Record r = rs.next();
962+
Assert.assertEquals(Long.valueOf(100), r.getValue(0));
963+
}
968964
}

src/test/java/com/redislabs/redisgraph/exceptions/JRedisGraphErrorTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,12 @@ public void testContextExceptionFlow() {
138138
}
139139

140140
}
141+
142+
@Test
143+
public void timeoutExcpetion() {
144+
exceptionRule.expect(JRedisGraphRunTimeException.class);
145+
exceptionRule.expectMessage("Query timed out");
146+
147+
api.query("social", "UNWIND range(0,100000) AS x WITH x AS x WHERE x = 10000 RETURN x", 1L);
148+
}
141149
}

0 commit comments

Comments
 (0)