Repository: tinkerpop
Updated Branches:
  refs/heads/master 1526c2c55 -> 65d7a82ff


TINKERPOP-1714 GremlinExecutor checks for timeout from time script submitted

Prior to this change timeouts were considered from the time the script started 
evaluation which probably isn't in line with user expectations but also made it 
hard to clear the job queue on an overloaded server.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/ac19d5de
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/ac19d5de
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/ac19d5de

Branch: refs/heads/master
Commit: ac19d5dec659a1a8f399d5a11a4812774eebeca7
Parents: 402678b
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Thu Jul 6 11:49:21 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Thu Jul 6 11:49:21 2017 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 .../gremlin/groovy/engine/GremlinExecutor.java  | 39 ++++++--------------
 2 files changed, 13 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ac19d5de/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 96e79ab..da85ebb 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -28,6 +28,7 @@ TinkerPop 3.2.6 (Release Date: NOT OFFICIALLY RELEASED YET)
 
 This release also includes changes from <<release-3-1-8, 3.1.8>>.
 
+* `GremlinExecutor` begins timeout of script evaluation at the time the script 
was submitted and not from the time it began evaluation.
 * `ReferenceFactory` and `DetachedFactory` now detach elements in collections 
accordingly.
 * Deprecated the `useMapperFromGraph` configuration option for Gremlin Server 
serializers.
 * `JavaTranslator` is now smart about handling `BulkSet` and `Tree`.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ac19d5de/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutor.java
----------------------------------------------------------------------
diff --git 
a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutor.java
 
b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutor.java
index 8802793..d646a8c 100644
--- 
a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutor.java
+++ 
b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutor.java
@@ -52,9 +52,9 @@ import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 import java.util.concurrent.FutureTask;
 import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -279,31 +279,6 @@ public class GremlinExecutor implements AutoCloseable {
 
         final CompletableFuture<Object> evaluationFuture = new 
CompletableFuture<>();
         final FutureTask<Void> evalFuture = new FutureTask<>(() -> {
-
-            if (scriptEvalTimeOut > 0) {
-                final Thread scriptEvalThread = Thread.currentThread();
-
-                logger.debug("Schedule timeout for script - {} - in thread 
[{}]", script, scriptEvalThread.getName());
-
-                // Schedule a timeout in the thread pool for future execution
-                final ScheduledFuture<?> sf = 
scheduledExecutorService.schedule(() -> {
-                    logger.warn("Timing out script - {} - in thread [{}]", 
script, Thread.currentThread().getName());
-                    if (!evaluationFuture.isDone()) 
scriptEvalThread.interrupt();
-                }, scriptEvalTimeOut, TimeUnit.MILLISECONDS);
-
-                // Cancel the scheduled timeout if the eval future is complete 
or the script evaluation failed
-                // with exception
-                evaluationFuture.handleAsync((v, t) -> {
-                    if (!sf.isDone()) {
-                        logger.debug("Killing scheduled timeout on script 
evaluation - {} - as the eval completed (possibly with exception).", script);
-                        sf.cancel(true);
-                    }
-
-                    // no return is necessary - nothing downstream is 
concerned with what happens in here
-                    return null;
-                }, scheduledExecutorService);
-            }
-
             try {
                 lifeCycle.getBeforeEval().orElse(beforeEval).accept(bindings);
 
@@ -349,7 +324,17 @@ public class GremlinExecutor implements AutoCloseable {
             return null;
         });
 
-        executorService.execute(evalFuture);
+        final Future<?> executionFuture = executorService.submit(evalFuture);
+        if (scriptEvalTimeOut > 0) {
+            // Schedule a timeout in the thread pool for future execution
+            scheduledExecutorService.schedule(() -> {
+                if (executionFuture.cancel(true)) {
+                    
lifeCycle.getAfterTimeout().orElse(afterTimeout).accept(bindings);
+                    evaluationFuture.completeExceptionally(new 
TimeoutException(
+                            String.format("Script evaluation exceeded the 
configured 'scriptEvaluationTimeout' threshold of %s ms or evaluation was 
otherwise cancelled directly for request [%s]", scriptEvalTimeOut, script)));
+                }
+            }, scriptEvalTimeOut, TimeUnit.MILLISECONDS);
+        }
 
         return evaluationFuture;
     }

Reply via email to