You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by xi...@apache.org on 2024/10/10 21:21:17 UTC

(tinkerpop) 02/02: add bulked as ctx attr to preserve state & added remote feature test for bulked config

This is an automated email from the ASF dual-hosted git repository.

xiazcy pushed a commit to branch graphbinary-bulked-response
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 7490784ae77b7565713080f49aeb6aa9fa9bd6db
Author: Yang Xia <55...@users.noreply.github.com>
AuthorDate: Thu Oct 10 14:21:08 2024 -0700

    add bulked as ctx attr to preserve state & added remote feature test for bulked config
---
 .../driver/handler/GremlinResponseHandler.java     |  3 +-
 .../handler/HttpGremlinResponseStreamDecoder.java  |  5 +++
 .../server/handler/HttpGremlinEndpointHandler.java |  7 +--
 .../GraphBinaryLangBulkedRemoteFeatureTest.java    | 51 ++++++++++++++++++++++
 .../gremlin/driver/remote/RemoteWorld.java         | 10 +++++
 .../io.cucumber.core.backend.ObjectFactory         |  1 +
 6 files changed, 73 insertions(+), 4 deletions(-)

diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/GremlinResponseHandler.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/GremlinResponseHandler.java
index b44e26bcc2..3dfd983481 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/GremlinResponseHandler.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/GremlinResponseHandler.java
@@ -74,8 +74,9 @@ public class GremlinResponseHandler extends SimpleChannelInboundHandler<Response
 
         if ((null == statusCode) || (statusCode == HttpResponseStatus.OK)) {
             final List<Object> data = response.getResult().getData();
+            final boolean bulked = (boolean) channelHandlerContext.channel().attr(AttributeKey.valueOf("isBulked")).get();
             // unrolls the collection into individual results to be handled by the queue.
-            if (response.getResult().isBulked()) {
+            if (bulked) {
                 for (Iterator<Object> iter = data.iterator(); iter.hasNext(); ) {
                     Object obj = iter.next();
                     long bulk = (long) iter.next();
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/HttpGremlinResponseStreamDecoder.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/HttpGremlinResponseStreamDecoder.java
index 5c8c38edf9..16400ad9e6 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/HttpGremlinResponseStreamDecoder.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/HttpGremlinResponseStreamDecoder.java
@@ -49,6 +49,7 @@ public class HttpGremlinResponseStreamDecoder extends MessageToMessageDecoder<De
     private static final AttributeKey<HttpResponseStatus> RESPONSE_STATUS = AttributeKey.valueOf("responseStatus");
     private static final AttributeKey<String> RESPONSE_ENCODING = AttributeKey.valueOf("responseSerializer");
     private static final AttributeKey<Long> BYTES_READ = AttributeKey.valueOf("bytesRead");
+    private static final AttributeKey<Boolean> IS_BULKED = AttributeKey.valueOf("isBulked");
 
     private final MessageSerializer<?> serializer;
     private final long maxResponseContentLength;
@@ -62,6 +63,7 @@ public class HttpGremlinResponseStreamDecoder extends MessageToMessageDecoder<De
     @Override
     protected void decode(ChannelHandlerContext ctx, DefaultHttpObject msg, List<Object> out) throws Exception {
         final Attribute<Boolean> isFirstChunk = ((AttributeMap) ctx).attr(IS_FIRST_CHUNK);
+        final Attribute<Boolean> isBulked = ((AttributeMap) ctx).attr(IS_BULKED);
         final Attribute<HttpResponseStatus> responseStatus = ((AttributeMap) ctx).attr(RESPONSE_STATUS);
         final Attribute<String> responseEncoding = ((AttributeMap) ctx).attr(RESPONSE_ENCODING);
 
@@ -95,6 +97,9 @@ public class HttpGremlinResponseStreamDecoder extends MessageToMessageDecoder<De
                     out.add(response);
                 } else {
                     final ResponseMessage chunk = serializer.readChunk(content, isFirstChunk.get());
+                    if (isFirstChunk.get()){
+                        isBulked.set(chunk.getResult().isBulked());
+                    }
                     isFirstChunk.set(false);
                     out.add(chunk);
                 }
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
index e92ba8d5a0..c5b4f1f6e7 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
@@ -313,8 +313,10 @@ public class HttpGremlinEndpointHandler extends SimpleChannelInboundHandler<Requ
         final Bindings mergedBindings = mergeBindingsFromRequest(context, new SimpleBindings(graphManager.getAsBindings()));
         final Object result = scriptEngine.eval(message.getGremlin(), mergedBindings);
 
-        final boolean bulking = Objects.equals(context.getChannelHandlerContext().channel().attr(StateKey.REQUEST_HEADERS).get().get(Tokens.BULKED), "true")
-                || (args.containsKey(Tokens.BULKED) && (boolean) args.get(Tokens.BULKED));
+        final boolean bulking = ((Objects.equals(context.getChannelHandlerContext().channel().attr(StateKey.REQUEST_HEADERS).get().get(Tokens.BULKED), "true")
+                && result instanceof Traversal)
+                || (args.containsKey(Tokens.BULKED) && (boolean) args.get(Tokens.BULKED))
+                && Objects.equals(language, "gremlin-lang"));
 
         if (bulking) {
             // optimization for driver requests
@@ -421,7 +423,6 @@ public class HttpGremlinEndpointHandler extends SimpleChannelInboundHandler<Requ
             // while waiting for the client to catch up
             if (aggregate.size() < resultIterationBatchSize && itty.hasNext()) {
                 if (bulking) {
-                    // bulking will return
                     Traverser traverser = (Traverser) itty.next();
                     aggregate.add(traverser.get());
                     aggregate.add(traverser.bulk());
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangBulkedRemoteFeatureTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangBulkedRemoteFeatureTest.java
new file mode 100644
index 0000000000..1e5b0a7317
--- /dev/null
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/GraphBinaryLangBulkedRemoteFeatureTest.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.driver.remote;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Stage;
+import io.cucumber.guice.CucumberModules;
+import io.cucumber.junit.Cucumber;
+import io.cucumber.junit.CucumberOptions;
+import org.apache.tinkerpop.gremlin.features.AbstractGuiceFactory;
+import org.apache.tinkerpop.gremlin.features.World;
+import org.junit.runner.RunWith;
+
+@RunWith(Cucumber.class)
+@CucumberOptions(
+        tags = "not @RemoteOnly and not @GraphComputerOnly and not @AllowNullPropertyValues",
+        glue = { "org.apache.tinkerpop.gremlin.features" },
+        objectFactory = GraphBinaryLangBulkedRemoteFeatureTest.RemoteGuiceFactory.class,
+        features = { "classpath:/org/apache/tinkerpop/gremlin/test/features" },
+        plugin = {"progress", "junit:target/cucumber.xml"})
+public class GraphBinaryLangBulkedRemoteFeatureTest extends AbstractFeatureTest {
+    public static class RemoteGuiceFactory extends AbstractGuiceFactory {
+        public RemoteGuiceFactory() {
+            super(Guice.createInjector(Stage.PRODUCTION, CucumberModules.createScenarioModule(), new ServiceModule()));
+        }
+    }
+
+    public static final class ServiceModule extends AbstractModule {
+        @Override
+        protected void configure() {
+            bind(World.class).to(RemoteWorld.GraphBinaryLangBulkedRemoteWorld.class);
+        }
+    }
+}
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java
index b1c66c1d39..84109b080e 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/RemoteWorld.java
@@ -169,6 +169,16 @@ public abstract class RemoteWorld implements World {
         }
     }
 
+    public static class GraphBinaryLangBulkedRemoteWorld extends RemoteWorld {
+        public GraphBinaryLangBulkedRemoteWorld() { super(createTestCluster(Serializers.GRAPHBINARY_V4)); }
+
+        @Override
+        public GraphTraversalSource getGraphTraversalSource(final LoadGraphWith.GraphData graphData) {
+            final GraphTraversalSource g = super.getGraphTraversalSource(graphData);
+            return g.with("language", "gremlin-lang").with("bulked", true);
+        }
+    }
+
     public static class GraphBinaryGroovyRemoteWorld extends RemoteWorld {
         public GraphBinaryGroovyRemoteWorld() { super(createTestCluster(Serializers.GRAPHBINARY_V4)); }
 
diff --git a/gremlin-server/src/test/resources/META-INF/services/io.cucumber.core.backend.ObjectFactory b/gremlin-server/src/test/resources/META-INF/services/io.cucumber.core.backend.ObjectFactory
index 5b6b888d13..7b70b113b0 100644
--- a/gremlin-server/src/test/resources/META-INF/services/io.cucumber.core.backend.ObjectFactory
+++ b/gremlin-server/src/test/resources/META-INF/services/io.cucumber.core.backend.ObjectFactory
@@ -1,3 +1,4 @@
 org.apache.tinkerpop.gremlin.driver.remote.GraphBinaryLangRemoteFeatureTest$RemoteGuiceFactory
+org.apache.tinkerpop.gremlin.driver.remote.GraphBinaryLangBulkedRemoteFeatureTest$RemoteGuiceFactory
 org.apache.tinkerpop.gremlin.driver.remote.GraphBinaryGroovyRemoteFeatureTest$RemoteGuiceFactory
 org.apache.tinkerpop.gremlin.driver.remote.GraphBinaryRemoteComputerFeatureTest$RemoteGuiceFactory