i wrote a rest api that connects to google firestore as a backend. I have a users collection and want to ensure that each user document has a unique username. My first approach was to query the database for a matching document with same username and if it is found, then the user has to choose another one (on registration).
Here is my corresponding code (golang)
func (service *Service) CreateUser(ctx context.Context, user domains.User) (domains.User, error) {
var err error
err = domains.ValidateNewUser(user)
if err != nil {
return user, err
}
// Check if email already exists
unique, err := service.CheckEmailUniqueness(ctx, user.Email)
if err != nil {
return user, err
} else if !unique {
return user, ErrEmailExists
}
// Check if user already exists
unique, err = service.CheckUsernameUniqueness(ctx, user.Username)
if err != nil {
return user, err
} else if !unique {
return user, ErrUsernameExists
}
docRef, _, err := service.Client.Collection("users").Add(ctx, user)
if err != nil {
return user, ErrCreatingUser
}
user.UserID = docRef.ID
return user, nil
}
func (service *Service) CheckUsernameUniqueness(ctx context.Context, username string) (bool, error) {
iter := service.Client.Collection("users").Where("username", "==", username).Documents(ctx)
usernameExists := false
for {
_, err := iter.Next()
if err == iterator.Done {
break
}
if err != nil {
return false, err
}
usernameExists = true
break
}
return !usernameExists, nil
}
But how can you prevent race conditions in this case? Like when 2 different users want to take the same username and their requests are processed by two different instances of my rest server. I am very inexperienced with firestore and NoSQL in general, so pls excuse me if i dont understand anything crucial.