My User
object that I want to create and store in the datastore has an email
, and a username
. How do I make sure when creating my User
object that another User
object doesn't also have either the same email
or the same username
?
If I just do a query to see if any other users have already used the username or the email, then there could be a race condition.
UPDATE:
The solution I'm currently considering is to use the MemCache to implement a locking mechanism. I would acquire 2 locks before trying to store the User
object in the datastore. First a lock that locks based on email
, then another that locks based on username
.
Since creating new User
objects only happens at user registration time, and it's even rarer that two people try to use either the same username or the same email, I think it's okay to take the performance hit of locking.
I'm thinking of using the MemCache locking code that is here: http://appengine-cookbook.appspot.com/recipe/mutex-using-memcache-api/
What do you guys think?
Try storing your User with their email as the key_name
. This can be done in one simple step:
MyUser.get_or_insert(email)
Getting your MyUser
by an email is also easy:
MyUser.get_by_key_name(email)
See this similar question: add properties to users google app engine
So that solves the problem of two users with the same email. To do the same for usernames, perform the "get users with this username" query and the "insert a user with this username" in a transaction (this is what get_or_insert()
does behind the scenes).
You can catch a TransactionFailedError
to find cases when another user "takes" that username during your transaction.
You definitely don't want to use a memcache mutex, since that while
loop waiting for the lock to free up can spend a lot of your memcache API call quota.
If you use the JPA impl of datastore, you just have to set the annotation
@Column(unique=true) Field field
This way the db will reject your insert/update.. i guess it's implemented by gdatastore, it's not a big matter for me to give a "technical error" to the user on such a specific case... but anyway you could catch a constraintviolation exception. I guess JDO also have this.
But actually i don't even know if you'r using Python or Java...
In Java as far as i know you can do a select request in a transaction...
About transactions you should also check what is transaction isolation and how it works on GAE...
精彩评论