NodeJS, ExpressJS, Mongoose 4.4, Nonce для параллелизма и Document.update
У меня есть следующая комбинация, 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
Тем не менее, когда код входит в окончательный.then (// обновление ответа), я вижу raw.n (numberActed) = 1, но база данных никогда не обновляется?
Ответы, вероятно, близки, но мне не хватает этого. Чего мне не хватает в этом?
1 ответ
После комментария @blakes_seven я смог удалить использование nonce и применить обновления, используя атомарные модификаторы. Вот обновленный проверенный код.
//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!'})
}
};