2012-04-29 59 views
2

我目前正在嘗試使用rails和Mongoid開發一個簡單的基於web的遊戲。我遇到了一些併發問題,我不知道如何解決。併發和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'代碼。

我非常感謝有關如何解決此問題的任何想法。

但我越來越覺得用這種方式做用戶同步是相當不切實際的,而且還有更好的方法。所以對其他技術可以完成相同的事情的建議將不勝感激!

回答

3

聽起來像你想mongo findAndModify命令,它允許你原子檢索和更新一行。

可惜mongoid不會出現暴露蒙戈API的一部分,所以它看起來像你必須下降到驅動程序級別爲這一個位:

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

默認情況下,返回對象包括所做的修改,但如果你願意,你可以把這個在(通{:新=>真})

返回的值是原始哈希,如果我的記憶是正確的,你可以做Battle.instantiate(doc)得到一個Battle對象。

+0

嗨!感謝您的回覆。然而,我不能得到這個命令的工作。我得到的輸出是:Mongo :: OperationFailure(數據庫命令'findandmodify'失敗:(errmsg:'no such cmd'; bad cmd:'{「findandmodify」=>「battles」,「query」=> {「opponent」 => BSON :: ObjectId('4f970eb047911507fe000205'),「submitted」=> true},「update」=> {「$ set」=> {「resolving」=> true}},「new」=> true}' ;確定:'0.0')。): 我試圖讓它工作一個小時左右,但不知道爲什麼它沒有。需要我提到我對mongo來說很新穎嗎? :) – EasyPush 2012-04-29 20:19:30

+0

哦,我正在運行的確切命令如下: battle = Battle.collection.find_and_modify(query:{opponent:current_user._id,submitted:true},update:{'$ set'=> { resolving:true}},:new => true) – EasyPush 2012-04-29 20:21:55

+0

你運行的是哪個版本的mongo? – 2012-04-29 20:29:03