2

我目前正在尝试使用 Rails 和 Mongoid 开发一个简单的基于 Web 的游戏。我遇到了一些我不确定如何解决的并发问题。

问题是我不确定如何在 Mongoid 中原子地进行检查并根据它采取行动。

这是控制器代码相关部分的示例,可让您了解我正在尝试做什么:

battle = current_user.battle
battle.submitted = true
battle.save

if Battle.where(opponent: current_user._id, submitted: true, resolving: false).any?
  battle.update_attribute(:resolving, true)
  #Resolve turn

两个用户之间发生了一场战斗,但我只希望其中一个线程运行#Resolve 轮次。现在,除非我完全关闭,否则两个线程都可以一个接一个地检查条件,但在将解析设置为 true 之前,因此两个线程最终都会运行“#Resolve turn”代码。

我将非常感谢有关如何解决此问题的任何想法。

然而,我越来越感觉以这种方式进行用户同步是相当不切实际的,而且完全有更好的方法。因此,我们将不胜感激对可以完成相同任务的其他技术的建议!

4

1 回答 1

3

听起来您想要 mongo findAndModify命令,它允许您以原子方式检索和更新一行。

不幸的是,mongoid 似乎没有公开 mongo api 的这一部分,所以看起来你必须降级到驱动程序级别来处理这一点:

battle = Battle.collection.find_and_modify(query: {oppenent: current_user._id, ...},
                                           update: {'$set' => {resolving: true})

默认情况下,返回的对象包括所做的修改,但您可以根据需要打开它(通过 {:new => true})

返回的值是原始散列,如果我的记忆正确,您可以Battle.instantiate(doc)取回一个Battle对象。

于 2012-04-29T08:23:54.983 回答