Skip to content

clojurewerkz.neocons.rest.relationships/maybe-create creates more than one relation between two nodes on concurrent calls #22

Closed
tutysara opened this Issue Mar 4, 2013 · 8 comments

2 participants

@tutysara
tutysara commented Mar 4, 2013

Hi,
clojurewerkz.neocons.rest.relationships/maybe-create creates more than one relation between two nodes on concurrent calls.
I couldn't reproduce it on every occasion, but it occurs sporadically.
Here is the sample code that triggers this.

(defn get-root                                                                                                                                   
  "Returns the entity root node given the entity name                                                                                                  
   Created and relates to root node with :contains relation for new additions"
  [entityname]
  (let [idx-roots (nn/create-index "idx-roots")
        entity-root (nn/create-unique-in-index
                     (:name idx-roots)
                    "type"
                     entityname
                     {:type entityname})                     
        root (nn/get 0)]
     (nrel/maybe-create root entity-root :contains)
    entity-root))

;; realize a seq and keep in mem

(def res (take 500 (repeat "test")))
(pmap #(do 
              (Thread/sleep 300)
               (get-root %)) res)

This creates more than one :contains relation between node(0) and the entity-node (node of type "test")

Result

neo4j-sh (0)$ start root=node(0) match root-[:contains]->entityroot return entityroot;
+-------------------------+
| entityroot |
+-------------------------+
| Node[7642]{type:"test"} |
| Node[7642]{type:"test"} |
| Node[7642]{type:"test"} |
| Node[7642]{type:"test"} |
+-------------------------+
4 rows
1 ms

@michaelklishin
Owner

It takes time (an HTTP request) to fetch existing relationships in order to check whether a new one should be created.
Neocons won't (and can't) synchronize this for you. Use Cypher or batch API if you need to create relationships
in bulk concurrently.

@tutysara
tutysara commented Mar 4, 2013

Man, too fast. yeah, seen that from code. But the document says nothing about being single threaded so, thought of checking whether you had any plans to synchronize it. Would be better if the platform provided something like in the implementation of create-unique-in-index. Will check out the batch api and see if it fits my requirement. thx.

@michaelklishin
Owner

Starting with Neo4J 1.8, Cypher can be used to create relationships. In this case, the condition will be evaluated
in the server, which should perform the necessary synchronization.

@michaelklishin
Owner

Another idea is to make maybe-create use Cypher under the hood. For Neocons 1.1, we can do that because
it will require Neo4J Server 1.8 anyway.

@michaelklishin
Owner

@tutysara take a look at the example in 15.19.1, it seems to do what you need, with uniqueness checks performed by the server.

@michaelklishin michaelklishin pushed a commit that referenced this issue Mar 4, 2013
Michael Klishin Add a test that demonstrates how unique relationships can be created
References #22.
473be6b
@tutysara
tutysara commented Mar 4, 2013

thx you, that is useful. Found this - http://stackoverflow.com/questions/11354401/in-cypher-how-can-i-create-a-relationship-if-it-doesnt-exist-update-property, and wrote a cypher version of maybe-create. Testing my code.

@michaelklishin
Owner

One limitation of Cypher at the moment is inability to specify relationship types via a parameter. So we cannot move
quite a few functions to Cypher internally.

@tutysara
tutysara commented Mar 4, 2013

Thx for the updates. Didn't knew this, tried various combinations and finally went back to (format ) in my maybe-create implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.