2016-05-17 5 views
2

Мое серверное приложение (используя node.js, mongodb, mongoose) имеет набор документов, для которых важно, чтобы два клиентских приложения не могли изменять их одновременно, не видя модификации друг друга.Предотвращение одновременного доступа к документам в 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() 
    } 
    }) 
}) 

Проблема заключается в следующем:

Когда один документ пользователя сохраняется одновременно двумя клиентскими приложениями, возможно, что они чередуют между предварительно крюком и фактические операции сохранения? То, что я имею в виду следующее, представьте время происходит слева направо и v быть номер версии (которая сохраняется Спасите):

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

Результирующее в App1 экономии то, что был изменен тем (по App2), и он не может заметить, что он был изменен. Обновление App2 полностью потеряно.

Мой вопрос может сводиться к следующему: выполнить предварительный крюк Mongoose и метод сохранения на одном атомном шаге?

Если нет, не могли бы вы дать мне предложение о том, как исправить эту проблему, чтобы ни одно обновление не терялось?

Спасибо!

ответ

2

MongoDB имеет findAndModify, который для одного подходящего документа является атомной операцией.

Mongoose имеет различные методы, которые используют этот метод, и я думаю, что они удовлетворят ваш случай использования:

другой решение (тот, который сам Мангуст а также для его own document versioning) заключается в использовании шаблона Update Document if Current.

+0

спасибо, что работает. Особенно шаблон, который вы предложили, поскольку он позволяет проверять версию документа перед попыткой обновления. – Zxifer

Смежные вопросы