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.

Reply via email to