This is an automated email from the ASF dual-hosted git repository. spmallette pushed a commit to branch TINKERPOP-2514 in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 8729fd4ce1711b29bc0b90670e87df33e91f4f09 Author: Stephen Mallette <stepm...@amazon.com> AuthorDate: Wed Feb 17 17:26:00 2021 -0500 TINKERPOP-2514 Prevent two request ids to be pending at same time --- CHANGELOG.asciidoc | 1 + .../tinkerpop/gremlin/driver/Connection.java | 4 ++++ .../gremlin/server/GremlinDriverIntegrateTest.java | 28 +++++++++++++++++++--- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 06777b3..a2b9c47 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -23,6 +23,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima [[release-3-4-11]] === TinkerPop 3.4.11 (Release Date: NOT OFFICIALLY RELEASED YET) +* Prevented Java driver from sending multiple request messages with the same identifier. * Improved error message for `property(T,Object)` when mutating graph elements. * Added method caching for GraphSON 3.0 deserialization of `P` and `TextP` instances. * Fixed bug with Javascript Groovy `Translator` when generating Gremlin with multiple embedded traversals. diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Connection.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Connection.java index c3bc00d..897fedd 100644 --- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Connection.java +++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Connection.java @@ -220,6 +220,10 @@ final class Connection { } public ChannelPromise write(final RequestMessage requestMessage, final CompletableFuture<ResultSet> resultQueueSetup) { + // dont allow the same request id to be used as one that is already in the queue + if (pending.containsKey(requestMessage.getRequestId())) + throw new IllegalStateException(String.format("There is already a request pending with an id of: %s", requestMessage.getRequestId())); + // once there is a completed write, then create a traverser for the result set and complete // the promise so that the client knows that that it can start checking for results. final Connection thisConnection = this; diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java index 2aefd2b..f256e51 100644 --- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java +++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java @@ -65,7 +65,6 @@ import org.slf4j.LoggerFactory; import java.awt.Color; import java.io.File; -import java.net.ConnectException; import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; @@ -80,8 +79,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; @@ -91,7 +90,6 @@ import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.endsWith; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.collection.IsIterableContainingInOrder.contains; import static org.hamcrest.core.AllOf.allOf; import static org.hamcrest.number.OrderingComparison.greaterThan; import static org.hamcrest.number.OrderingComparison.lessThanOrEqualTo; @@ -1835,4 +1833,28 @@ public class GremlinDriverIntegrateTest extends AbstractGremlinServerIntegration assertTrue(cluster != null); cluster.close(); } + + @Test + public void shouldNotHangWhenSameRequestIdIsUsed() throws Exception { + final Cluster cluster = TestClientFactory.build().maxConnectionPoolSize(1).minConnectionPoolSize(1).create(); + final Client client = cluster.connect(); + final UUID requestId = UUID.randomUUID(); + + final Future<ResultSet> result1 = client.submitAsync("Thread.sleep(2000);100", + RequestOptions.build().overrideRequestId(requestId).create()); + + // wait for some business to happen on the server + Thread.sleep(100); + try { + // re-use the id and fail + client.submit("1+1+97", RequestOptions.build().overrideRequestId(requestId).create()); + fail("Request should not have been sent due to duplicate id"); + } catch(Exception ex) { + // should get a rejection here + final Throwable root = ExceptionUtils.getRootCause(ex); + assertThat(root.getMessage(), startsWith("There is already a request pending with an id of:")); + } + + assertEquals(100, result1.get().one().getInt()); + } }