我已经打了一个小的困境!我有一个名为票处理;被调用时将其设置一个用户的投票,以任何他们有回升。要记住他们以前捡到的选择,我店里面详细介绍他们目前的投票设置为VoteRecord选项。

当然,它们的投票在第一时间,我要创建对象和存储它。但是,连续的选票应该只是改变现有VoteRecord的价值。但是最后他还是这个问题:在某些情况下可以创建了两个VoteRecords。这是罕见的(仅适用于所有500票发生过一次,到目前为止,我们已经看到了),但仍然很糟糕,当它。

这个问题是因为两个独立的处理器基本上都做到这一点:

query = VoteRecord.all().filter('user =', session.user).filter('poll =', poll)

if query.count(1) > 0:
 vote = query[0]

 poll.votes[vote.option] -= 1
 poll.votes[option] += 1
 poll.put()

 vote.option = option
 vote.updated = datetime.now()
 vote.put()
else:
 vote = VoteRecord()
 vote.user = session.user
 vote.poll = poll
 vote.option = option
 vote.put()

 poll.votes[option] += 1
 poll.put()

 session.user.votes += 1
 session.user.xp += 3
 session.user.put()

 incr('votes')

我的问题是:什么是最有效的,并处理这些请求,同时确保最快的方式,没有请求丢失,没有要求创建两个VoteRecord对象

有帮助吗?

解决方案

的问题是这一部分:

if vote.count(1) == 0:
    obj = VoteRecord()
    obj.user = user
    obj.option = option
    obj.put()

如果没有交易,你的代码可以在这个顺序有两种解释实例上运行:

if vote.count(1) == 0:
    obj = VoteRecord()
    obj.user = user


if vote.count(1) == 0:
    obj = VoteRecord()
    obj.user = user
    obj.option = option
    obj.put()


    obj.option = option
    obj.put()

或其任何组合怪异。问题是计数测试再次运行放已发生之前,使所述第二螺纹穿过条件代替第二的第一部分。

可以通过将在一个函数的代码,然后使用修正此

db.run_in_transaction()

要运行该函数。

但问题是你似乎依赖于通过为决策逻辑的查询需要被放置在事务返回对象的个数。如果你读了谷歌I / O会谈或看组,你会看到,这是不推荐的。那是因为你不能transactionalize查询。相反,你应该的交易功能之外将计为一个实体价值的地方,因为它的查询,然后通过该实体的交易功能的关键。

下面是一个检查的实体特性的交易功能的一个例子。它的传递的键作为参数:

def checkAndLockPage(pageKey):
  page = db.get(pageKey)
  if page.locked:
    return False
  else:
    page.locked = True
    page.put()
    return True

在一个时间只有一个用户可以锁定该实体,并且永远不会有任何重复的锁。

其他提示

要做到这一点,最简单的方法就是使用键名称的投票对象,并使用Model.get_or_insert。首先,拿出你的键名命名方案 - 投票后命名它是一个好主意 - 然后做一个get_or_insert获取或创建相关实体:

vote = VoteRecord.get_or_insert(pollname, parent=session.user, user=session.user, poll=poll, option=option)
if vote.option != option:
  # Record already existed; we need to update it
  vote.option = option
  vote.put()
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top