views:

53

answers:

1

When someone signs up for my website they must sign up with a unique user name. My current pseudocode for this is:

if(datastore.nameIsAvailable(name)){
    datastore.createUser(name);
}

How do I make sure that in between the time when nameIsAvailable returns true, and the createUser is finished, another instance of my app doesn't create a user with the same name?

+2  A: 

You could do a query for the name:

appuser = AppUser.all().filter('name =', name).get()
if appuser:
  # user already has this name
else:
  # it's all yours!

...or better yet have the user's name be the key_name for your AppUser:

appuser = AppUser.get_by_key(name)
if appuser:
  # user already has this name
else:
  # it's all yours!

...and even better:

appuser = AppUser.get_or_insert(name)
# appuser is now either the existing user with this name,
# or a new user with this name!

Having your name be the entity's key_name means that it will always and forever be unique, and looking up a user by their name will be as fast as possible.

(This is presuming you're using Python, if not, I can add a Java example, but the idea is the same)

Jason Hall
but what prevents the concurrency problem of 2 instances running the code at the same time, and both instances see the name as available because the commit to the datastore didn't happen until after both instances called `AppUser.get_by_key(name)`?
Kyle
Jason Hall
I think you should mention that the first two options are not thread safe. The question is specifically concerned with concurency.
Peter Recore
Excellent point. Running in a transaction (like get_or_insert() does), an exception will be raised if another user beats you to that username during the transaction.
Jason Hall