Repository: tinkerpop Updated Branches: refs/heads/master ea7b6d954 -> cd9cf9dad
TINKERPOP-1756 Added an EmbeddedRemoteConnection. This enables a "remote" to be mocked to actually run locally in the same JVM. Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/c59393ff Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/c59393ff Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/c59393ff Branch: refs/heads/master Commit: c59393ff46b17d55cf438635a30830c24d6773e6 Parents: 60a34d1 Author: Stephen Mallette <sp...@genoprime.com> Authored: Fri Sep 1 15:42:20 2017 -0400 Committer: Stephen Mallette <sp...@genoprime.com> Committed: Mon Sep 11 13:29:17 2017 -0400 ---------------------------------------------------------------------- CHANGELOG.asciidoc | 1 + .../upgrade/release-3.2.x-incubating.asciidoc | 17 ++++- .../remote/EmbeddedRemoteConnection.java | 75 ++++++++++++++++++++ .../traversal/EmbeddedRemoteTraversal.java | 56 +++++++++++++++ .../EmbeddedRemoteTraversalSideEffects.java | 47 ++++++++++++ .../process/traversal/CoreTraversalTest.java | 18 ++++- 6 files changed, 209 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c59393ff/CHANGELOG.asciidoc ---------------------------------------------------------------------- diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index ff0948a..c15835c 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -27,6 +27,7 @@ TinkerPop 3.2.7 (Release Date: NOT OFFICIALLY RELEASED YET) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Bump to Jackson 2.8.10. +* Added an `EmbeddedRemoteConnection` so that it's possible to mimic a remote connection within the same JVM. * The Console's `plugin.txt` file is only updated if there were manually uninstalled plugins. * Fixed a bug in `MatchStep` where mid-traversal `where()` variables were not being considered in start-scope. * Generalized `MatchStep` to locally compute all clauses with barriers (not just reducing barriers). http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c59393ff/docs/src/upgrade/release-3.2.x-incubating.asciidoc ---------------------------------------------------------------------- diff --git a/docs/src/upgrade/release-3.2.x-incubating.asciidoc b/docs/src/upgrade/release-3.2.x-incubating.asciidoc index 25d776a..407cc89 100644 --- a/docs/src/upgrade/release-3.2.x-incubating.asciidoc +++ b/docs/src/upgrade/release-3.2.x-incubating.asciidoc @@ -25,11 +25,25 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima TinkerPop 3.2.7 --------------- -*NOT OFFICIALLY RELEASED YET* +*Release Date: NOT OFFICIALLY RELEASED YET* Upgrading for Users ~~~~~~~~~~~~~~~~~~~ +Please see the link:https://github.com/apache/tinkerpop/blob/3.2.7/CHANGELOG.asciidoc#release-3-2-7[changelog] for a complete list of all the modifications that are part of this release. + +Embedded Remote Connection +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As Gremlin Language Variants (GLVs) expand their usage and use of `withRemote()` becomes more common, the need to mock +the "remote" in unit tests increases. To simplify mocking in Java, the new `EmbeddedRemoteConnection` provides a +simple way to provide a "remote" that is actually local to the same JVM. + +See: link:https://issues.apache.org/jira/browse/TINKERPOP-1756[TINKERPOP-1756] + +Changes to match() +~~~~~~~~~~~~~~~~~~ + The `match()`-step has been generalized to suppor the local scoping of all barrier steps, not just reducing barrier steps. Previously, the `order().limit()` clause would have worked globally yielding: @@ -60,7 +74,6 @@ This includes steps like `count()`, `min()`, `max()`, `sum()`, `group()`, `group generalized this behavior to all barriers and thus, adds `aggregate()`, `dedup()`, `range()`, `limit()`, `tail()`, and `order()` to the list of locally computed clauses. - TinkerPop 3.2.6 --------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c59393ff/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/EmbeddedRemoteConnection.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/EmbeddedRemoteConnection.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/EmbeddedRemoteConnection.java new file mode 100644 index 0000000..da1a03a --- /dev/null +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/EmbeddedRemoteConnection.java @@ -0,0 +1,75 @@ +/* + * 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.process.remote; + +import org.apache.tinkerpop.gremlin.jsr223.JavaTranslator; +import org.apache.tinkerpop.gremlin.process.remote.traversal.EmbeddedRemoteTraversal; +import org.apache.tinkerpop.gremlin.process.remote.traversal.RemoteTraversal; +import org.apache.tinkerpop.gremlin.process.traversal.Bytecode; +import org.apache.tinkerpop.gremlin.process.traversal.Traversal; +import org.apache.tinkerpop.gremlin.process.traversal.Traverser; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.structure.Graph; + +import java.util.Iterator; + +/** + * Allows a {@link RemoteConnection} to be submitted to a "local" {@link Graph} instance thus simulating a connection + * to a remote source. Basic usage is as follows: + * + * <pre> + * {@code + * // Using TinkerGraph here but any embedded Graph instance would suffice + * Graph graph = TinkerFactory.createModern(); + * GraphTraversalSource g = graph.traversal(); + * + * // setup the remote as normal but give it the embedded "g" so that it executes against that + * final Graph remote = EmptyGraph.instance(); + * GraphTraversalSource simulatedRemoteG = remote.traversal().withRemote(new EmbeddedRemoteConnection(g)); + * assertEquals(6, simulatedRemoteG.V().count().next().intValue()); + * } + * </pre> + * + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public class EmbeddedRemoteConnection implements RemoteConnection { + + private final GraphTraversalSource g; + + public EmbeddedRemoteConnection(final GraphTraversalSource g) { + this.g = g; + } + + @Override + public <E> Iterator<Traverser.Admin<E>> submit(final Traversal<?, E> traversal) throws RemoteConnectionException { + throw new UnsupportedOperationException("This method is deprecated and no longer used internally"); + } + + @Override + public <E> RemoteTraversal<?, E> submit(final Bytecode bytecode) throws RemoteConnectionException { + // this method is technically deprecated but it's still being used on the 3.2.x/3.3.x lines of code. it is + // called by submitAsync() in RemoteConnection itself. this implementation should suffice for now + return new EmbeddedRemoteTraversal(JavaTranslator.of(g).translate(bytecode)); + } + + @Override + public void close() throws Exception { + g.close(); + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c59393ff/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/EmbeddedRemoteTraversal.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/EmbeddedRemoteTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/EmbeddedRemoteTraversal.java new file mode 100644 index 0000000..cc12c1a --- /dev/null +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/EmbeddedRemoteTraversal.java @@ -0,0 +1,56 @@ +/* + * 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.process.remote.traversal; + +import org.apache.tinkerpop.gremlin.process.remote.EmbeddedRemoteConnection; +import org.apache.tinkerpop.gremlin.process.traversal.Traversal; +import org.apache.tinkerpop.gremlin.process.traversal.Traverser; + +/** + * Generated by the {@link EmbeddedRemoteConnection} to help simulate a remote traversal execution within the same JVM. + * + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public class EmbeddedRemoteTraversal<S,E> extends AbstractRemoteTraversal<S,E> { + private final Traversal<S, E> t; + + public EmbeddedRemoteTraversal(final Traversal<S,E> t) { + this.t = t; + } + + @Override + public Traverser.Admin<E> nextTraverser() { + return t.asAdmin().nextTraverser(); + } + + @Override + public RemoteTraversalSideEffects getSideEffects() { + return new EmbeddedRemoteTraversalSideEffects(t.asAdmin().getSideEffects()); + } + + @Override + public boolean hasNext() { + return t.hasNext(); + } + + @Override + public E next() { + return t.next(); + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c59393ff/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/EmbeddedRemoteTraversalSideEffects.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/EmbeddedRemoteTraversalSideEffects.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/EmbeddedRemoteTraversalSideEffects.java new file mode 100644 index 0000000..b878f5d --- /dev/null +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/EmbeddedRemoteTraversalSideEffects.java @@ -0,0 +1,47 @@ +/* + * 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.process.remote.traversal; + +import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects; + +import java.util.Set; + +/** + * Generated by the {@link EmbeddedRemoteTraversal} to help simulate a remote traversal side-effects within the same JVM. + * + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public class EmbeddedRemoteTraversalSideEffects extends AbstractRemoteTraversalSideEffects { + + private final TraversalSideEffects sideEffects; + + public EmbeddedRemoteTraversalSideEffects(final TraversalSideEffects sideEffects) { + this.sideEffects = sideEffects; + } + + @Override + public <V> V get(final String key) throws IllegalArgumentException { + return sideEffects.get(key); + } + + @Override + public Set<String> keys() { + return sideEffects.keys(); + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c59393ff/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/CoreTraversalTest.java ---------------------------------------------------------------------- diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/CoreTraversalTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/CoreTraversalTest.java index 68f8217..6cffe2c 100644 --- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/CoreTraversalTest.java +++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/CoreTraversalTest.java @@ -22,7 +22,9 @@ import org.apache.tinkerpop.gremlin.ExceptionCoverage; import org.apache.tinkerpop.gremlin.FeatureRequirement; import org.apache.tinkerpop.gremlin.LoadGraphWith; import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest; +import org.apache.tinkerpop.gremlin.process.remote.EmbeddedRemoteConnection; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet; import org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException; @@ -30,6 +32,7 @@ import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Graph; import org.apache.tinkerpop.gremlin.structure.Transaction; import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph; import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils; import org.junit.Ignore; import org.junit.Test; @@ -293,10 +296,10 @@ public class CoreTraversalTest extends AbstractGremlinProcessTest { public void shouldThrowFastNoSuchElementExceptionInNestedTraversals() { //The nested traversal should throw a regular FastNoSuchElementException - GraphTraversal<Object, Object> nestedTraversal = __.has("name", "foo"); - GraphTraversal<Vertex, Object> traversal = g.V().has("name", "marko").branch(nestedTraversal); + final GraphTraversal<Object, Object> nestedTraversal = __.has("name", "foo"); + final GraphTraversal<Vertex, Object> traversal = g.V().has("name", "marko").branch(nestedTraversal); - GraphTraversal.Admin<Object, Object> nestedTraversalAdmin = nestedTraversal.asAdmin(); + final GraphTraversal.Admin<Object, Object> nestedTraversalAdmin = nestedTraversal.asAdmin(); nestedTraversalAdmin.reset(); nestedTraversalAdmin.addStart(nestedTraversalAdmin.getTraverserGenerator().generate(g.V().has("name", "marko").next(), (Step)traversal.asAdmin().getStartStep(), 1l)); @@ -307,4 +310,13 @@ public class CoreTraversalTest extends AbstractGremlinProcessTest { } } + + @Test + @LoadGraphWith(MODERN) + public void shouldAllowEmbeddedRemoteConnectionUsage() { + final Graph remote = EmptyGraph.instance(); + final GraphTraversalSource simulatedRemoteG = remote.traversal().withRemote(new EmbeddedRemoteConnection(g)); + assertEquals(6, simulatedRemoteG.V().count().next().intValue()); + assertEquals("marko", simulatedRemoteG.V().has("name", "marko").values("name").next()); + } }