You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2016/03/29 20:27:22 UTC

incubator-tinkerpop git commit: Minor adjustment to allow LifeCycle override of scriptEvaluationTimeout

Repository: incubator-tinkerpop
Updated Branches:
  refs/heads/tp31 3cb9bfcf9 -> 733a3320a


Minor adjustment to allow LifeCycle override of scriptEvaluationTimeout

This opens up the option to pass in a per-request scriptEvaluationTimeout in Gremlin Server. That might be useful for mixed load queries over OLAP/OLTP. CTR.


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

Branch: refs/heads/tp31
Commit: 733a3320aec5e04bdcca1e1f0f1e8e28e6a04539
Parents: 3cb9bfc
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Tue Mar 29 14:25:42 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Tue Mar 29 14:25:42 2016 -0400

----------------------------------------------------------------------
 .../gremlin/groovy/engine/GremlinExecutor.java  | 27 +++++++++++++++---
 .../groovy/engine/GremlinExecutorTest.java      | 29 ++++++++++++++++++++
 2 files changed, 52 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/733a3320/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 edd421d..5ef8667 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
@@ -248,6 +248,9 @@ public class GremlinExecutor implements AutoCloseable {
         bindings.putAll(globalBindings);
         bindings.putAll(boundVars);
 
+        // override the timeout if the lifecycle has a value assigned
+        final long seto = lifeCycle.scriptEvaluationTimeoutOverride.orElse(scriptEvaluationTimeout);
+
         final CompletableFuture<Object> evaluationFuture = new CompletableFuture<>();
         final FutureTask<Void> f = new FutureTask<>(() -> {
             try {
@@ -282,7 +285,7 @@ public class GremlinExecutor implements AutoCloseable {
                 // check for that situation and convert to TimeoutException
                 if (root instanceof InterruptedException)
                     evaluationFuture.completeExceptionally(new TimeoutException(
-                            String.format("Script evaluation exceeded the configured 'scriptEvaluationTimeout' threshold of %s ms for request [%s]: %s", scriptEvaluationTimeout, script, root.getMessage())));
+                            String.format("Script evaluation exceeded the configured 'scriptEvaluationTimeout' threshold of %s ms for request [%s]: %s", seto, script, root.getMessage())));
                 else {
                     lifeCycle.getAfterFailure().orElse(afterFailure).accept(bindings, root);
                     evaluationFuture.completeExceptionally(root);
@@ -294,7 +297,7 @@ public class GremlinExecutor implements AutoCloseable {
 
         executorService.execute(f);
 
-        if (scriptEvaluationTimeout > 0) {
+        if (seto > 0) {
             // 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());
@@ -302,7 +305,7 @@ public class GremlinExecutor implements AutoCloseable {
                     lifeCycle.getAfterTimeout().orElse(afterTimeout).accept(bindings);
                     f.cancel(true);
                 }
-            }, scriptEvaluationTimeout, TimeUnit.MILLISECONDS);
+            }, seto, TimeUnit.MILLISECONDS);
 
             // Cancel the scheduled timeout if the eval future is complete or the script evaluation failed
             // with exception
@@ -539,7 +542,7 @@ public class GremlinExecutor implements AutoCloseable {
         }
 
         /**
-         * Replaces any settings provided by {@link #engineSettings(java.util.Map)}.
+         * Replaces any settings provided.
          */
         public Builder engineSettings(final Map<String, EngineSettings> settings) {
             this.settings = settings;
@@ -685,6 +688,7 @@ public class GremlinExecutor implements AutoCloseable {
         private final Optional<Consumer<Bindings>> afterSuccess;
         private final Optional<Consumer<Bindings>> afterTimeout;
         private final Optional<BiConsumer<Bindings, Throwable>> afterFailure;
+        private final Optional<Long> scriptEvaluationTimeoutOverride;
 
         private LifeCycle(final Builder builder) {
             beforeEval = Optional.ofNullable(builder.beforeEval);
@@ -693,6 +697,11 @@ public class GremlinExecutor implements AutoCloseable {
             afterSuccess = Optional.ofNullable(builder.afterSuccess);
             afterTimeout = Optional.ofNullable(builder.afterTimeout);
             afterFailure = Optional.ofNullable(builder.afterFailure);
+            scriptEvaluationTimeoutOverride = Optional.ofNullable(builder.scriptEvaluationTimeoutOverride);
+        }
+
+        public Optional<Long> getScriptEvaluationTimeoutOverride() {
+            return scriptEvaluationTimeoutOverride;
         }
 
         public Optional<Consumer<Bindings>> getBeforeEval() {
@@ -730,6 +739,7 @@ public class GremlinExecutor implements AutoCloseable {
             private Consumer<Bindings> afterSuccess = null;
             private Consumer<Bindings> afterTimeout = null;
             private BiConsumer<Bindings, Throwable> afterFailure = null;
+            private Long scriptEvaluationTimeoutOverride = null;
 
             /**
              * Specifies the function to execute prior to the script being evaluated.  This function can also be
@@ -786,6 +796,15 @@ public class GremlinExecutor implements AutoCloseable {
                 return this;
             }
 
+            /**
+             * An override to the global {@code scriptEvaluationTimeout} setting on the script engine. If this value
+             * is set to {@code null} (the default) it will use the global setting.
+             */
+            public Builder scriptEvaluationTimeoutOverride(final Long scriptEvaluationTimeoutOverride) {
+                this.scriptEvaluationTimeoutOverride = scriptEvaluationTimeoutOverride;
+                return this;
+            }
+
             public LifeCycle create() {
                 return new LifeCycle(this);
             }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/733a3320/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutorTest.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutorTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutorTest.java
index 22c1699..387f0a1 100644
--- a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutorTest.java
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/engine/GremlinExecutorTest.java
@@ -271,6 +271,35 @@ public class GremlinExecutorTest {
     }
 
     @Test
+    public void shouldTimeoutSleepingScriptViaOverrideOnLifeCycle() throws Exception {
+        final AtomicBoolean successCalled = new AtomicBoolean(false);
+        final AtomicBoolean failureCalled = new AtomicBoolean(false);
+
+        final CountDownLatch timeOutCount = new CountDownLatch(1);
+
+        final GremlinExecutor gremlinExecutor = GremlinExecutor.build()
+                .scriptEvaluationTimeout(10000)
+                .afterFailure((b, e) -> failureCalled.set(true))
+                .afterSuccess((b) -> successCalled.set(true))
+                .afterTimeout((b) -> timeOutCount.countDown()).create();
+        try {
+            final GremlinExecutor.LifeCycle lifeCycle = GremlinExecutor.LifeCycle.build()
+                    .scriptEvaluationTimeoutOverride(250L).create();
+            gremlinExecutor.eval("Thread.sleep(1000);10", "gremlin-groovy", new SimpleBindings(), lifeCycle).get();
+            fail("This script should have timed out with an exception");
+        } catch (Exception ex) {
+            assertEquals(TimeoutException.class, ex.getCause().getClass());
+        }
+
+        assertTrue(timeOutCount.await(2000, TimeUnit.MILLISECONDS));
+
+        assertFalse(successCalled.get());
+        assertFalse(failureCalled.get());
+        assertEquals(0, timeOutCount.getCount());
+        gremlinExecutor.close();
+    }
+
+    @Test
     public void shouldOverrideBeforeEval() throws Exception {
         final AtomicInteger called = new AtomicInteger(0);
         final GremlinExecutor gremlinExecutor = GremlinExecutor.build().beforeEval(b -> called.set(1)).create();