Hello, I'm currently in the process of migrating a Neo4j based project to OrientDB 2.1. Unfortunately i have some problems when handling concurrent graph operations.
I read the following documentation regarding concurrency and transaction handling but i have still problems understanding the issues that i'm getting. * https://orientdb.com/docs/last/Java-Multi-Threading.html * http://orientdb.com/docs/last/Concurrency.html I'm using OrientDB 2.1 in combination with the OGM Ferma <https://github.com/Syncleus/Ferma>. I created a small reproducer that contains two tests that illustrate my problems. The complete sources for the minimalistic reproducer can be found here: https://github.com/Jotschi/orientdb-concurrency-test 1. A minimalistic example that just uses OrientDB without Ferma. In this case i'm creating some graph element in Thread A and i try to update those element in Thread B without reloading those. The code works just fine when i include the graph.attach call but i don't understand what the consequences of this solution are or whether there is a better alternative to handle this usecase. @Test > public void testMultithreading() { > OrientGraph graph = factory.getTx(); > Vertex v2 = graph.addVertex(null); > Vertex v = graph.addVertex(null); > graph.commit(); > runAndWait(() -> { > // graph.attach((OrientElement) v); > v.setProperty("name", "new-name"); > v.addEdge("test", v2); > }); > } I get the following exception when i'm not including the graph.attach call. Exception in thread "Thread-3" java.lang.IllegalStateException: There is no > active graph instance for current element. Please either open connection to > your storage, or use detach/attach methods instead. > at > com.tinkerpop.blueprints.impls.orient.OrientElement.checkIfAttached(OrientElement.java:674) > at > com.tinkerpop.blueprints.impls.orient.OrientVertex.canCreateDynamicEdge(OrientVertex.java:1288) > at > com.tinkerpop.blueprints.impls.orient.OrientVertex.addEdge(OrientVertex.java:943) > at > com.tinkerpop.blueprints.impls.orient.OrientVertex.addEdge(OrientVertex.java:832) > at > com.gentics.test.orientdb.OrientDBTinkerpopMultithreadingTest.lambda$0(OrientDBTinkerpopMultithreadingTest.java:23) > at > com.gentics.test.orientdb.OrientDBTinkerpopMultithreadingTest$$Lambda$1/18342669.run(Unknown > > Source) > at java.lang.Thread.run(Thread.java:745) 2. The second test shows how i want to use OrientDB with ferma. In Thread A some graph elements are created and Thread B uses the existing objects/references to update those elements. Similar to the example shown above i got an Exception. @Test > public void testMultithreading() throws InterruptedException { > // Prepare some element and add them to the graph > Person p = addPersonWithFriends(fg); > p.setName("joe"); > CountDownLatch latch = new CountDownLatch(1); > runAndWait(() -> { > // Another thread is using the existing element references to to read and > update the graph from that position. > // graph.attach((OrientElement) p.getElement()); > manipulatePerson(p); > latch.countDown(); > }); > failingLatch(latch); > } I understand that i got this exception because the OrientVertex contains a ThreadLocal that stores the graph reference but it is still unclear to me how to resolve the issue. What i want to avoid is to reload the vertex using a new graph instance for that thread. Similar to the first test the graph.attach command resolves the issue but i don't understand why or whether this is actually a good approach. Exception in thread "Thread-3" java.lang.NullPointerException > at > com.tinkerpop.blueprints.impls.orient.OrientBaseGraph.getEdgeClassNames(OrientBaseGraph.java:292) > at > com.tinkerpop.blueprints.impls.orient.OrientVertex.getEdges(OrientVertex.java:1065) > at > com.tinkerpop.blueprints.impls.orient.OrientVertex.getEdges(OrientVertex.java:1045) > at > com.tinkerpop.blueprints.util.DefaultVertexQuery$DefaultVertexQueryIterable.<init>(DefaultVertexQuery.java:110) > at > com.tinkerpop.blueprints.util.DefaultVertexQuery.vertices(DefaultVertexQuery.java:84) > at > com.tinkerpop.pipes.transform.VertexQueryPipe.processNextStart(VertexQueryPipe.java:113) > at > com.tinkerpop.pipes.transform.VertexQueryPipe.processNextStart(VertexQueryPipe.java:19) > at com.tinkerpop.pipes.AbstractPipe.next(AbstractPipe.java:89) > at > com.tinkerpop.pipes.filter.PropertyFilterPipe.processNextStart(PropertyFilterPipe.java:27) > at > com.tinkerpop.pipes.filter.PropertyFilterPipe.processNextStart(PropertyFilterPipe.java:13) > at com.tinkerpop.pipes.AbstractPipe.next(AbstractPipe.java:89) > at com.tinkerpop.pipes.util.Pipeline.next(Pipeline.java:115) > at > com.syncleus.ferma.pipes.FermaGremlinPipeline.next(FermaGremlinPipeline.java:68) > at com.tinkerpop.pipes.util.PipeHelper.fillCollection(PipeHelper.java:52) > at > com.tinkerpop.gremlin.java.GremlinPipeline.toList(GremlinPipeline.java:1564) > at > com.syncleus.ferma.traversals.AbstractVertexTraversal.toListExplicit(AbstractVertexTraversal.java:506) > at com.gentics.test.Person.getFriends(Person.java:10) > at > com.gentics.test.orientdb.AbstractOrientDBTest.manipulatePerson(AbstractOrientDBTest.java:26) > at > com.gentics.test.orientdb.OrientDBFermaMultithreadingReducedTest.lambda$0(OrientDBFermaMultithreadingReducedTest.java:37) > at > com.gentics.test.orientdb.OrientDBFermaMultithreadingReducedTest$$Lambda$1/33502406.run(Unknown > > Source) > at java.lang.Thread.run(Thread.java:745) Greetings, Johannes -- --- You received this message because you are subscribed to the Google Groups "OrientDB" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
