2016-05-17 9 views
2

私のサーバーアプリケーション(node.js、mongodb、mongooseを使用)には、2つのクライアントアプリケーションが互いの変更を見ることなく同時に変更することができないことが重要な文書の集合があります。Mongooseの文書への同時アクセスの防止

これを防ぐには、ドキュメントのバージョンが有効かどうか(つまり、クライアントが最後に読み込んだもの)よりも高いかどうかを確認するスキーマのプリフックを追加しました。一見それは正常に動作します:

// Validate version number 
UserSchema.pre("save", function(next) { 
    var user = this 

    user.constructor.findById(user._id, function(err, userCurrent) { // userCurrent is the user that is currently in the db 
    if (err) return next(err) 
    if (userCurrent == null) return next() 

    if(userCurrent.docVersion > user.docVersion) { 
     return next(new Error("document was modified by someone else")) 
    } else { 
     user.docVersion = user.docVersion + 1 
     return next() 
    } 
    }) 
}) 

問題は以下の通りです:

1つのユーザー文書は2つのクライアントアプリケーションが同時に保存されている場合、それはこれらが前フックの間でインターリーブすることが可能です実際のセーブ操作は?私は何を意味することは、左から右とV(セーブで永続化される)バージョン番号であることに行く時間を想像し、以下の通りです:

App1: findById(pre)[v:1]         save[v->2] 
App2:      findById(pre)[v:1] save[v->2] 

(App2ので)その間に変更されたものを保存App1の中で、その結果、それが変更されたことに気づく方法はありません。 App2のアップデートは完全に失われます。

私の質問は、次のように沸騰する可能性があります。モンゴースのプリフックと保存方法は、1つのアトミックなステップで行われますか?

もしそうでなければ、この問題を修正してアップデートが失われないように私に提案してもらえますか?

ありがとうございました!

答えて

2

MongoDBにはfindAndModifyがあります。これは、一致する単一のドキュメントの場合、アトミックな操作です。

マングースはこの方法を使用するさまざまな方法を持っている、と私は、彼らはあなたのユースケースに合うだろうと思います。

別の解決策(それは私たちがMongoose自身であるまた、own document versioningの場合)は、Update Document if Currentパターンを使用することです。

+0

ありがとうございました。特に、あなたが提案したパターンは、更新を試みる前にドキュメントのバージョンチェックが可能です。 – Zxifer

関連する問題