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)

Reply via email to