【问题标题】:Concurrency and Mongoid并发和 Mongoid
【发布时间】:2012-04-29 07:57:21
【问题描述】:

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

问题是我不确定如何在 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”代码。

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

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

【问题讨论】:

    标签: ruby-on-rails mongodb concurrency mongoid


    【解决方案1】:

    听起来你想要 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 对象。

    【讨论】:

    • 嗨!感谢您的回复。但是,我无法使该命令起作用。我得到的输出是: Mongo::OperationFailure (Database command 'findandmodify' failed: (errmsg: 'no such cmd'; bad cmd: '{"findandmodify"=>"battles", "query"=>{"opponent" =>BSON::ObjectId('4f970eb047911507fe000205'), "提交"=>true}, "更新"=>{"$set"=>{"resolving"=>true}}, "new"=>true}' ; ok: '0.0').): 我试图让它工作一个小时左右,但不知道为什么它没有。需要我提一下我对 mongo 很陌生吗? :)
    • 哦,我正在运行的确切命令如下:battle = Battle.collection.find_and_modify(query: {opponent: current_user._id, submit: true}, update: {'$set ' => {resolving: true}}, :new => true)
    • 你运行的是什么版本的mongo?
    • 啊,我正在运行 1.2.2。假设由于某种原因它是最新的!看到find and modify是1.3以后才有的,我更新再试试!
    猜你喜欢
    • 1970-01-01
    • 2011-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-07
    • 2011-02-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多