Oliver Towers created TINKERPOP-2437:
----------------------------------------
Summary: gremlin-driver hangs if
ResultSet.statusAttributes().get() is called when the request throws
Key: TINKERPOP-2437
URL: https://issues.apache.org/jira/browse/TINKERPOP-2437
Project: TinkerPop
Issue Type: Bug
Components: driver
Affects Versions: 3.4.8
Reporter: Oliver Towers
Issue is present in gremlin-driver when an error is thrown on the request.
If ResultSet.statusAttributes() is blocked on before other calls are made
ResultSet, then the calling thread will hang if an exception is thrown.
If other ResultSet futures are are blocked on, then exception should be
propagated correctly.
h2. Repro:
{code:java}
ResultSet results = client.submit(queryWhichFails, params); Double
requestCharge =
(Double)results.statusAttributes().get().get("x-ms-request-charge");
CompletableFuture<List<Result>> completableFutureResults = results.all();{code}
h2. Cause:
>From the tinkerpop github source
>[ResultSet.java|https://github.com/apache/tinkerpop/blob/d1a3fa147d1f009ae57274827c9b59426dfc6e58/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ResultSet.java]
> this is the statusAttributes method:
{code:java}
public CompletableFuture<Map<String,Object>> statusAttributes() {
final CompletableFuture<Map<String,Object>> attrs = new
CompletableFuture<>();
readCompleted.thenRun(() -> attrs.complete(null ==
resultQueue.getStatusAttributes() ? Collections.emptyMap() :
resultQueue.getStatusAttributes()));
return attrs;
}{code}
This will ensure that the attrs CompleteableFuture returned by the method
completes readCompleted finishes. However, it lacks handling for
readCompleted.exceptionally(...), so in the case of readCompleted hitting an
exception, the returned attrs CompletableFuture is never completed/closed,
causing the caller thread to hang.
h2. Workaround:
Avoid blocking on ResutSet.statusAttributes() before ResultSet.all() or other
methods which will materialize the results fully.
For example:
{code:java}
ResultSet results = client.submit(queryWhichFails, params);
CompletableFuture<List<Result>> completableFutureResults = results.all();
Double requestCharge =
(Double)results.statusAttributes().get().get("x-ms-request-charge");
{code}
h2. Fix:
Add readCompleted.exceptionally(...) callback for CompletableFuture returned by
statusAttributes():
{code:java}
public CompletableFuture<Map<String,Object>> statusAttributes() {
final CompletableFuture<Map<String,Object>> attrs = new
CompletableFuture<>();
readCompleted.thenRun(() -> attrs.complete(null ==
resultQueue.getStatusAttributes() ? Collections.emptyMap() :
resultQueue.getStatusAttributes()));
readCompleted.exceptionally(t -> {
attrs.completeExceptionally(t);
return null;
});
return attrs;
}{code}
--
This message was sent by Atlassian Jira
(v8.3.4#803005)