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

Reply via email to