В Google App Engine, как мне избежать создания дублирующихся сущностей с одинаковым атрибутом? - PullRequest
3 голосов
/ 05 сентября 2010

Я пытаюсь добавить транзакцию, чтобы не создавать две сущности с одинаковым атрибутом. В моем приложении я создаю новый проигрыватель каждый раз, когда вижу нового пользователя Google, вошедшего в систему. Моя текущая реализация иногда создает дубликаты игроков, когда новый пользователь Google выполняет несколько вызовов json в течение нескольких миллисекунд. Когда я добавляю транзакцию, подобную той, что была прокомментирована здесь, я получаю различные ошибки. Какой самый простой способ убедиться, что я никогда не создаю два объекта игрока с одинаковым user_id?

  def get_player_from_user(self, user_id):
    player = Player.all().filter('user_id =', user_id).get()    
    if not player:
        #This can result in duplicate players with the same user_id being created. 
        player = self.create_new_player(user_id)
        #This is what I'm trying to do. 
        #player = db.run_in_transaction(self.create_new_player, user_id=user_id)
    return player

  def create_new_player(self,user_id):
        #Check one more time for an existing user_id match.  
        player = Player.all().filter('user_id =', user_id).get()
        if player:
           return player

        player = Player()
        player.user_id = user.user_id()
        player.put()
        return player

Ответы [ 2 ]

4 голосов
/ 05 сентября 2010

Используйте имя пользователя (или другой идентификатор) в качестве имени ключа и используйте get_or_insert для транзакционного создания нового объекта или возврата существующего. Код Сахида не будет работать, потому что без транзакции условие гонки все еще возможно.

1 голос
/ 05 сентября 2010

Может быть, вы можете использовать имя ключа и get_by_key_name лучше, чем фильтр.

 def create_new_player(self,user_id):
    key_name = "player/%s" % user_id
    player = Player.get_by_key_name (key_name)
    if player is None:
      player = Player (key_name=key_name, user_id=user_id)
      player.put ()
    return player

С последним комментарием Ника я обновил свой код, так что лучшее решение:

    def create_new_player(self,user_id):
      key_name = "player/%s" % user_id
      player = Player.get_or_insert (key_name=key_name, user_id=user_id)
      return player
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...