I well imagine your suggestion Michael, but I don't think it could fit my use case.
Indeed, let's assume 2 users that simultaneously clicks on the same button. This button triggers the following action: "According to the user that has triggered the action, find externally some possible pairs, and check if they already exist in the graph database". "If they exist, link the user and each found node with a neo4j relationship" The trick is that every user can potentially have any kind of existing node-pair in the graph. The first user must for instance be linked to the node-pair number 3 and 4 and the second user be linked to the 4 et 5. Two parallel processes locking for the 4 would end up in a warning of deadlock (specified by neo4j), if those processes have both started their own transaction. Thus, it simply impossible (I guess) to gather the data to be updated in a specific routee directly. (meaning having a router splitting in multiple updating actors) To improve performance compared to a whole single-threaded method, I thought about having some routees (actors) named "NodePairChecker", in order to at least parallelize the external calls. Each result (collection of node-pairs) provided by the NodePairChecker would then be sent to a unique actor, aiming to update the concerned nodes. Does it make sense? It's the first time I'm faced to deadlock in Neo4j :) Thanks Michael On Friday, March 14, 2014 12:58:43 PM UTC+1, Michael Hunger wrote: > > You can just consistently route them. > > Hash your node-identifier and send them to the same actor. > > Cheers, > > Michael > > ---- > (michael > <http://twitter.com/mesirii>)-[:SUPPORTS]->(*YOU*)-[:USE]->(Neo4j<http://neo4j.org> > ) > Learn Online <http://neo4j.org/learn/online_course>, > Offline<http://www.neo4j.org/events> or > Read a Book <http://graphdatabases.com> (in Deutsch<http://bit.ly/das-buch> > ) > We're trading T-shirts for cool Graph Models <http://bit.ly/graphgist> > > > > > > > > Am 14.03.2014 um 12:46 schrieb Michael Azerhad > <[email protected]<javascript:> > >: > > The trick is I can't know in advance which nodes I have to update. > They come to the fly, regarding users' actions on client. > I guess that a single-threaded solution is the must for this use case... > in order to avoid parallel transactions trying to update node-pairs (or > same node) in the same time. > But it sounds no performant..I'm going to think for a better solution, if > existing... > > Besides, as my main database is hosted at GrapheneDB, I'm forced to use > the REST mode. (so simple mapping is adapted) (and it works great) > Embedded mode for my local environment and for being able to be flexible > the day I would pass production on embedded mode, we never know.. > ImpermanentGraphDatabase for my tests. > > > > On Friday, March 14, 2014 12:16:45 PM UTC+1, Michael Hunger wrote: >> >> What you can do on the akka level is to group the nodes that are updated >> so that you always batch updates that are of the same node (or node-pair) >> together, then you can even update all of them in the same tx which >> increases throughput. >> >> Are you using the aspectj mapping? or simple mapping? (The first is more >> performant as it just writes through to the db (within a tx). >> >> Cheers, >> >> Michael >> >> ---- >> (michael <http://twitter.com/mesirii>)-[:SUPPORTS]->(*YOU*)-[:USE]->( >> Neo4j <http://neo4j.org/>) >> Learn Online <http://neo4j.org/learn/online_course>, >> Offline<http://www.neo4j.org/events> or >> Read a Book <http://graphdatabases.com/> (in Deutsch<http://bit.ly/das-buch> >> ) >> We're trading T-shirts for cool Graph Models <http://bit.ly/graphgist> >> >> >> >> >> >> >> >> Am 14.03.2014 um 12:11 schrieb Michael Azerhad <[email protected]>: >> >> Hi Michael, >> >> The whole works :) except one improvement I want to make: >> >> The deadlock was caused due to multiple threads (Akka Actor) updating the >> same Node or its relationships in parallel transaction. >> Is there a Neo4j way to avoid taking a transaction that would share >> objects with another one? >> Or should I play with classic (independent of Neo4j lib) thread >> synchronisation. >> >> >> >> On Friday, March 14, 2014 9:21:00 AM UTC+1, Michael Hunger wrote: >>> >>> Yep your code was correct except the tx close. >>> >>> You want to wrap that into a try-with-resource block, not sure how that >>> looks in scala. >>> >>> Remote server has no transactions (currently) each request is one tx. >>> >>> Cheers, >>> >>> Michael >>> >>> ---- >>> (michael <http://twitter.com/mesirii>)-[:SUPPORTS]->(*YOU*)-[:USE]->( >>> Neo4j <http://neo4j.org/>) >>> Learn Online <http://neo4j.org/learn/online_course>, >>> Offline<http://www.neo4j.org/events> or >>> Read a Book <http://graphdatabases.com/> (in Deutsch<http://bit.ly/das-buch> >>> ) >>> We're trading T-shirts for cool Graph Models <http://bit.ly/graphgist> >>> >>> >>> >>> >>> >>> >>> >>> Am 14.03.2014 um 03:18 schrieb Michael Azerhad <[email protected]>: >>> >>> I've just fixed the deadlock: I was missing the "tx.close()" statement >>> at the end of each of my transaction. >>> Now I seek for the reason why my cars is empty, after the save.. using >>> embedded mode. >>> When using REST mode, it still works. >>> >>> I would just like to have the confirmation that the way I exposed above >>> is correct. >>> I will then search myself for the reason :) >>> >>> Thanks a lot :) >>> >>> On Friday, March 14, 2014 2:57:16 AM UTC+1, Michael Azerhad wrote: >>>> >>>> It sounds to be a deadlock: >>>> >>>> A deadlock scenario has been detected and avoided. This means that two >>>> or more transactions, which were holding locks, were wanting to await >>>> locks held by one another,which would have resulted in a deadlock >>>> between these transactions. This exception was thrown instead of >>>> ending up in that deadlock. >>>> >>>> >>>> See the deadlock section in the Neo4j manual for how to avoid this: >>>> http://docs.neo4j.org/chunked/stable/transactions-deadlocks.html >>>> >>>> >>>> Details: 'Transaction(98, >>>> owner:"play-akka.actor.default-dispatcher-6")[STATUS_ACTIVE,Resources=1] >>>> can't wait on resource RWLock[NodeLock[id=0]] since => Transaction(98, >>>> owner:"play-akka.actor.default-dispatcher-6")[STATUS_ACTIVE,Resources=1 >>>> ] <-[:HELD_BY]- RWLock[NodeLock[id=3]] <-[:WAITING_FOR]- Transaction( >>>> 101, owner:"play-akka.actor.default-dispatcher-9")[STATUS_ACTIVE, >>>> Resources=1] <-[:HELD_BY]- RWLock[NodeLock[id=0]]'. >>>> at >>>> org.springframework.data.neo4j.support.Neo4jExceptionTranslator.translateExceptionIfPossible(Neo4jExceptionTranslator.java:67) >>>> at >>>> org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59) >>>> at >>>> org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) >>>> at >>>> org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147) >>>> at >>>> org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) >>>> at >>>> org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) >>>> at $Proxy57.save(Unknown Source) >>>> at >>>> com.myApp.infrastructure.persistence.user.Neo4jUserRepository.save(Neo4jUserRepository.scala:15) >>>> >>>> >>>> On Friday, March 14, 2014 2:45:17 AM UTC+1, Michael Hunger wrote: >>>>> >>>>> How does it fail? >>>>> D >>>>> Am 14.03.2014 um 01:54 schrieb Michael Azerhad <[email protected]>: >>>>> >>>>> Hi, >>>>> >>>>> I try to update the relationship of a Node that is a collection. >>>>> Example: User has a list of Cars. >>>>> >>>>> Firstly, I saved the User with the Cars set beforehand, and the whole >>>>> works with embedded mode and REST mode. >>>>> >>>>> Now, I want to add one Car to the list of this User. >>>>> >>>>> So I tried the following: (Scala code but easy to figure out) >>>>> >>>>> val tx = graphDatabaseService.beginTx() >>>>> val user = userRepository.findById(1) >>>>> user.cars.clear() //cars being the relationships >>>>> (Set[Cars]) >>>>> user.cars.add(new Car("Ferrari")) >>>>> userRepository.save(user) // fail with embedded >>>>> but works with REST mode ! >>>>> tx.success() >>>>> >>>>> >>>>> Is it the right way to update the collection ? >>>>> Is there something special on the embedded mode handling ? >>>>> >>>>> Thanks, >>>>> >>>>> Michael >>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "Neo4j" 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. >>>>> >>>>> >>>>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Neo4j" 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. >>> >>> >>> >> -- >> You received this message because you are subscribed to the Google Groups >> "Neo4j" 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. >> >> >> > -- > You received this message because you are subscribed to the Google Groups > "Neo4j" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected] <javascript:>. > For more options, visit https://groups.google.com/d/optout. > > > -- You received this message because you are subscribed to the Google Groups "Neo4j" 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.
