Uploaded image for project: 'TinkerPop'
  1. TinkerPop
  2. TINKERPOP-2437

gremlin-driver hangs if ResultSet.statusAttributes().get() is called when the request throws

    XMLWordPrintableJSON

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Minor
    • Resolution: Fixed
    • Affects Version/s: 3.4.8
    • Fix Version/s: 3.5.0, 3.4.9
    • Component/s: driver
    • Labels:
      None

      Description

      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.

      Repro:

      ResultSet results = client.submit(queryWhichFails, params); Double requestCharge = (Double)results.statusAttributes().get().get("x-ms-request-charge");
      CompletableFuture<List<Result>> completableFutureResults = results.all();

      Cause:

      From the tinkerpop github source ResultSet.java this is the statusAttributes method:

       

      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;
       }

       

      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.

      Workaround:

      Avoid blocking on ResutSet.statusAttributes() before ResultSet.all() or other methods which will materialize the results fully. 

      For example:

      ResultSet results = client.submit(queryWhichFails, params);
      CompletableFuture<List<Result>> completableFutureResults = results.all();
      Double requestCharge = (Double)results.statusAttributes().get().get("x-ms-request-charge");
      

      Fix:

      Add readCompleted.exceptionally(...) callback for CompletableFuture returned by statusAttributes():

      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;
       }

       

       

        Attachments

          Activity

            People

            • Assignee:
              divijvaidya Divij Vaidya
              Reporter:
              olivertowers Oliver Towers
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: