Hi, I've seen this come up a number of times in various forms on the mailing list, but -- while there are some scattered answers here and there -- there doesn't seem to be much of a definitive solution. The problem I'm looking to solve is basic uniqueness (e.g. for creating an account -- unique username or email address); to make matters more complicated, I'd like to do this over the REST interface.
In the a non-REST use of Neo4j, it sounds like I could achieve this by doing the following: 1. Begin a transaction 2. Acquire a write lock on a UserRef supernode, say by attempting to delete the property __WRITE_LOCK__ (which will fail if the property doesn't exist, say) 3. Check if username is in users index 4. If it is, cancel transaction and fail 5. Otherwise, add a User node, relate it back to the UserRef node, and add it to the index 6. Release lock on UserRef supernode by re-adding __WRITE_LOCK__ property 7. Commit transaction First -- does this sound roughly sound? Assuming that any operation that ever touches the index agrees to first "acquire" a write lock in this manner, are there any tricky concurrency issues (maybe out-of-sync indexes, or the index.get(key,v).size() function being "almost correct") that I'm missing? To complicate matters, I'd _like_ to do this with REST, not the least reason because my main project code is in Python, and neo4j.py seems to be relatively unmaintained compared to the REST client. It's my understanding that transactions are handled using the batch interface. The only way to make the transaction fail is if any given operation returns a non-2xx status code. Thus, the 'if value is found in an index' thing is somewhat difficult to implement given the basic REST primitives. After cozying up with the code for a number of hours last night, my first real foray into Java programming, it appears that I can achieve the behaviour I want by introducing a REST plugin (an unmanaged extension would be cleaner, but the big warning and limited documentation dissuaded me) that throws an exception if a value _is_ found in a given index (which will cause the plugin invoker to return a 4xx response). Now my workflow over REST looks like this: 1. Begin transaction (e.g., start a batch request to the server), issuing the following commands: 2. Attempt to delete __WRITE_LOCK__ from UserRef node (will 4xx if property is non-existent) 3. POST to extension, to check if username is in users index (4xx if it exists) 3a. Transaction will fail at this point if user is in index 4. Add a User node 5. Relate it back to the UserRef node 5. Add it to the index 6. Release lock on UserRef supernode by re-adding __WRITE_LOCK__ property 7. Finish HTTP request, done This seems to work, but, again, are there any blind-spots that I'm unaware of? How about if this goes to a HA cluster? Finally, somewhat related, are some concerns with the batch API back-reference capability. This appears to manifest itself as a blind string-replace of '{[id]}' in provided fields. This _seems_ like it could have some security/annoying bug concerns relating to user-provided data (local portion of email address includes the substring '{1}', for example, which is valid per the email spec). I currently don't see any way around this except to restrict user input. Any thoughts? Anyway, thanks for any comments and responses! -Tony Wooster -- View this message in context: http://neo4j-community-discussions.438527.n3.nabble.com/REST-Transactions-and-Uniqueness-tp3360054p3360054.html Sent from the Neo4j Community Discussions mailing list archive at Nabble.com. _______________________________________________ Neo4j mailing list User@lists.neo4j.org https://lists.neo4j.org/mailman/listinfo/user