0

NodeJS、Express、MongoDB、Mongoose の組み合わせがあります。同時編集を可能にするために、マングースの約束でナンスを実装しました。以下を参照してください。

//schema
var item_schema = {
    //_id: {type: Schema.ObjectId, required: true},
    name: {type: String, required: true, index: { unique: true }},
    code: {type: String, required: true, index: { unique: true }},
    date_time_created: {type: Date, required: true},
    date_time_updated: {type: Date, required: true},
    nonce: {type: Schema.ObjectId}
};

//model
var item_model = mongoose.model('item', schema);

//update
var concurrency_update = function(req, res, retries) {

    var promise = model.findById(req.params.id).exec();

    var updated_nonce = mongoose.Types.ObjectId();

    promise.then(function(document){ //find document response

        if(!document) {
            res.status = 404;
            return Promise.reject( { "message" : req.params.id + ' document does not exist' } );
        }
        var now = new Date();
        if(req.body.code) {
            document.code = req.body.code;
            document.date_time_updated = now;
        }
        if(req.body.name) {
            document.name = req.body.name;
            document.date_time_updated = now;
        }
        if(!document.nonce) {
            document.nonce = updated_nonce;
            var old_nonce = document.nonce;
        }
        else {
            var old_nonce = document.nonce;
            document.nonce = updated_nonce;
        }
        return document.update({ "_id" : req.params.id, "nonce" : old_nonce }).exec();

    }).then(function(raw){ //update response

        var number_affected = raw.n;
        console.log(raw);
        if(!number_affected && retries < 10){
            //we weren't able to update the doc because someone else modified it first, retry
            console.log("Unable to update, retrying ", retries);
            //retry with a little delay
            setTimeout(function(){
                concurrency_update(req, res, (retries + 1));
            }, 20);
        } else if (retries >= 10){
            //there is probably something wrong, just return an error
            return Promise.reject({ "message" : "Couldn't update document after 10 retries in update"});
        } else {
            res.json({"message": req.params.id + ' document was update'});
        }

    }).catch(function(err){
        res.send(err.message);
    });

並行性の更新はこれに基づいています: http://www.mattpalmerlee.com/2014/03/22/a-pattern-for-handling-concurrent/

そしてマングースのドキュメントを読むと、更新はこれに基づいています。 http://mongoosejs.com/docs/api.html#document_Document-update

ただし、コードが最後の .then (//update 応答) に入ると、raw.n (numberAffected) = 1 が表示されますが、データベースは更新されませんか?

答えはおそらく近いですが、私はそれを見逃しています。これには何が欠けていますか?

4

1 に答える 1

0

@blakes_seven のコメントの後、nonce の使用を削除し、atomic 修飾子を使用して更新を適用することができました。これが更新されたテスト済みコードです。

//schema
var item_schema = {
    //_id: {type: Schema.ObjectId, required: true},
    name: {type: String, required: true, index: { unique: true }},
    code: {type: String, required: true, index: { unique: true }},
    date_time_created: {type: Date, required: true},
    date_time_updated: {type: Date, required: true},
    nonce: {type: Schema.ObjectId}
};

//model
var item_model = mongoose.model('item', schema);

//update
var concurrency_update = function(req, res, retries) {

    var updated_data = {};
    if(req.body.code) {
        updated_data.code = req.body.code;
    }
    if(req.body.name) {
        updated_data.name = req.body.name;
    }
    if(!req.body.name.nonce) {
        updated_data.nonce = mongoose.Types.ObjectId();
    }

    if(updated_data !== {}) {
        var update = {
            $currentDate: {
                date_time_updated: true
            },
            $set: updated_data
        };
        var promise = model.update({"_id": req.params.id}, update).exec();

        promise.then(function (raw) {

            var number_affected = raw.nModified;
            console.log(raw);
            if (!number_affected && retries < 10) {
                //we weren't able to update the doc because someone else modified it first, retry
                console.log("Unable to update, retrying ", retries);
                //retry with a little delay
                setTimeout(function () {
                    concurrency_update(req, res, (retries + 1));
                }, 20);
            } else if (retries >= 10) {
                //there is probably something wrong, just return an error
                return Promise.reject({"message": "Couldn't update document after 10 retries in update"});
            } else {
                res.json({"message": req.params.id + ' document was update'});
            }

        }).catch(function (err) {
            res.send(err.message);
        });
    }
    else {
        res.status = 400;
        res.send({"message": 'There is nothing specified in the payload to update!'})
    }
};
于 2016-02-26T11:58:43.583 に答える