Chris Chris - 3 months ago 10
reST (reStructuredText) Question

write lock behavior in neo4j cypher over transational REST api

I am using CYPHER like below (with Neo4j 2.2.3, over the transactional cypher REST endpoint) to atomically read and increment a 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 making REST posts like this, and I have now seen a case where two threads got the same counter value returned.

This behavior looks similar to what is described as a possible regression from 2.1 to 2.2 here: Neo4j 2.2 Cypher locking regression?

However, earlier it was suggested that this isn't possible in CYPHER (see comments here: http://stackoverflow.com/a/18486645) ... even earlier it seems to have been possible (see: http://stackoverflow.com/a/18450171)

Is there a CYPHER query, similar to above, that will reliably produce unique (monotonically increasing) counter values when there are multiple concurrent REST POSTs of the query?

Answer

In Neo4j, you need to obtain a write lock before you read and update the value. We do this as two statements in a single transaction (one REST call). We use MERGE/ON CREATE/ON MATCH, but I do not think that is necessary or would even work in your case. I believe this should work for you.

statement 1:

MATCH node WHERE id(node)={nodeId}
SET node.__lock=true
RETURN node.__lock

statement 2:

MATCH node WHERE id(node)={nodeId}
SET node.counter=COALESCE(node.counter,0) + 1
SET node.__lock=false
RETURN node.counter