Last active
August 25, 2016 15:56
-
-
Save sarmbruster/4feb9bb446ae580cf71deb83810f071b to your computer and use it in GitHub Desktop.
sample code for simulating merging two nodes and a relationship in between in a concurrent safe way
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private void mergeConnectedNodes(Label myLabel, RelationshipType relationshipType, String propertyKey, String valueA, String valueB) { | |
try (Transaction tx = db.beginTx()) { | |
// get or create start end node | |
Node a = mergeAndLockNode(myLabel, propertyKey, valueA); | |
Node b = mergeAndLockNode(myLabel, propertyKey, valueB); | |
grabLocksInConsistentOrder(tx, a,b); | |
boolean aIsCheaper = a.getDegree(relationshipType) < b.getDegree(relationshipType); | |
Node cheaperNode = aIsCheaper ? a : b; | |
Node otherNode = aIsCheaper ? b : a; | |
if (!hasRelationshipBetween(cheaperNode, otherNode, relationshipType)) { | |
cheaperNode.createRelationshipTo(otherNode, relationshipType); | |
} | |
tx.success(); | |
} | |
} | |
private boolean hasRelationshipBetween(Node cheaperNode, Node otherNode, RelationshipType relationshipType) { | |
boolean result = false; | |
for (Relationship r : cheaperNode.getRelationships(relationshipType)) { // consider direction here if reltype is directional in real life | |
if (r.getOtherNode(cheaperNode).equals(otherNode)) { | |
return true; | |
} | |
} | |
return result; | |
} | |
private Node mergeAndLockNode(Label myLabel, String propertyKey, Object propertyValue) { | |
Node node = db.findNode(myLabel, propertyKey, propertyValue); | |
if (node == null) { | |
node = db.createNode(myLabel); | |
node.setProperty(propertyKey, propertyValue); | |
} | |
return node; | |
} | |
private void grabLocksInConsistentOrder(Transaction tx, Node... nodes) { | |
SortedMap<Long, Node> orderedNodesById = new TreeMap<>(); | |
for (Node node : nodes) { | |
orderedNodesById.put(node.getId(), node); | |
} | |
for (Node node: orderedNodesById.values()) { | |
tx.acquireWriteLock(node); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment