Write blocking behavior in neo4j cypher over trans-national REST api
I am using CYPHER as shown below (with Neo4j 2.2.3, above transactional kef REST endpoint) to atomically read and increment the counter property on a node:
MATCH node WHERE id(node)={nodeId}
SET node.counter=COALESCE(node.counter,0) + 1
RETURN node.counter
I have multiple threads creating REST records like this and now I've seen a case where two threads got the same counter value.
This behavior is similar to what is described as a possible regression from 2.1 to 2.2: Neo4j 2.2 Cypher Lock Regression?
However, it has previously been suggested that this is not possible in CYPHER (see comments here: https://stackoverflow.com/a/1499298/ ... ) ... even before, it seems like it was possible (see: https://stackoverflow.com/a/2996999/) 2250118 / ... )
Is there a CYPHER request similar to the one above that will reliably generate unique (monotonically increasing) counter values โโwhen there are multiple concurrent REST requests?
source to share
In Neo4j, you need to acquire a write lock before reading and updating a value. We do this as two statements in one transaction (one REST call). We are using MERGE / ON CREATE / ON MATCH, but I don't think this is necessary or even will work in your case. I believe this should work for you.
expression 1:
MATCH node WHERE id(node)={nodeId}
SET node.__lock=true
RETURN node.__lock
expression 2:
MATCH node WHERE id(node)={nodeId}
SET node.counter=COALESCE(node.counter,0) + 1
SET node.__lock=false
RETURN node.counter
source to share
Adding to @SeanTimm's answer, you can explicitly block nodes via Cypher, if you are using the popular (and open source) APOC plugin for Neo4j, APOC has a choice of explicit blocking routines that can be called via Cypher such ascall apoc.lock.nodes([nodes])
If this option is available to you, it is probably preferable to some other hacky solutions.
More on neo4j-contrib.github.io/neo4j-apoc-procedures/#_locking
source to share