2015-12-02 3 views
0

У меня есть некоторые вопросы после чтения этого сообщения: Perform Two Phase Commits on MongodbMongoDB двухфазной Фиксация И Асинхронный Операция

Questions1: В посте, он определил пример обратно сделки. Мой вопрос - как выглядит код? Это просто объединить все в одну функцию, как это? Если нет, то HWO в вэнь организовать весь код в этой должности

var t = db.transactions.findOne({ state: "initial" }) 
db.transactions.update(
    { _id: t._id, state: "initial" }, 
    { 
     $set: { state: "pending" }, 
     $currentDate: { lastModified: true } 
    } 
) 
db.accounts.update(
    { _id: t.source, pendingTransactions: { $ne: t._id } }, 
    { $inc: { balance: -t.value }, $push: { pendingTransactions: t._id } } 
) 
db.accounts.update(
    { _id: t.destination, pendingTransactions: { $ne: t._id } }, 
    { $inc: { balance: t.value }, $push: { pendingTransactions: t._id } } 
) 
db.transactions.update(
    { _id: t._id, state: "pending" }, 
    { 
    $set: { state: "applied" }, 
    $currentDate: { lastModified: true } 
    } 
) 
db.accounts.update(
    { _id: t.source, pendingTransactions: t._id }, 
    { $pull: { pendingTransactions: t._id } } 
) 
db.accounts.update(
    { _id: t.destination, pendingTransactions: t._id }, 
    { $pull: { pendingTransactions: t._id } } 
) 
db.transactions.update(
    { _id: t._id, state: "applied" }, 
    { 
    $set: { state: "done" }, 
    $currentDate: { lastModified: true } 
    } 
) 

question2: С MongoDB гарантировать его работа атомная при работе с одним документом, то я могу просто обернуть все вышеуказанные блоки в обещания и цепи их вместе, поскольку каждый блок только модифицирует один документ.

ответ

1

Для второго вопроса вам не нужно ничего обернуть, update() уже возвращает обещание. Вы можете запустить их все асинхра как этого

var t = db.transactions.findOne({ state: "initial" }); 

var query1 = db.transactions.update(
    { _id: t._id, state: "initial" }, 
    { 
     $set: { state: "pending" }, 
     $currentDate: { lastModified: true } 
    } 
); 

var query2 = db.accounts.update(
    { _id: t.source, pendingTransactions: { $ne: t._id } }, 
    { $inc: { balance: -t.value }, $push: { pendingTransactions: t._id } } 
); 

Promise.all([query1, query2]).then(function done(params) { 
    console.log('all updates done'); 
}).catch(function catch(err) { 
    console.log(err); 
}); 

редактировать

Я быстро прочитал ссылку на MongoDB документ и от того, что я понимаю, две части совершить это попытка воссоздать поведение транзакций в SQL. Это выглядит следующим образом:

  • создать один документ (транзакции) для входа в будущем обновления существующих документов
    1. обновление существующих документов по мере необходимости (банковские счета в примере) < < первой фазы
    2. обновить сделку, когда два счета обновляются правильно < < второй фазы

Прочитав состояние транзакции, вы можете узнать, были ли эти две (или более) учетные записи обновлены правильно и находятся в чистом состоянии.

Код/псевдокод должен идти, как этого, используя обещания:

// create the transaction 
db.transactions.insert(
    { _id: 1, source: "A", destination: "B", value: 100, state: "initial", lastModified: new Date() } 
).then(function (err, transaction) { 
    // now you can start updating the accounts (first phase) 
    var query1 = db.accounts.update(
     { _id: t.source, pendingTransactions: { $ne: t._id } }, 
     { $inc: { balance: -t.value }, $push: { pendingTransactions: t._id } } 
    ); 
    var query2 = db.accounts.update(
     { _id: t.destination, pendingTransactions: { $ne: t._id } }, 
     { $inc: { balance: t.value }, $push: { pendingTransactions: t._id } } 
    ); 
    // the two accounts must be updated together 
    return Promise.all([query1, query2]); 
}).then(function (err, result) { 
    // accounts are update correctly, now update the transaction (second phase) 
    // the transaction id must be stored somewhere in the code before 
    return db.transactions.update(
     { _id: t._id, state: "pending" }, 
     { 
      $set: { state: "applied" }, 
      $currentDate: { lastModified: true } 
     } 
    ); 
}).then(function (err, result) { 
    // another updates on accounts if needed 
    // ... 
}).catch(function (err) { 
    // deal with all errors here 
}; 

Официальные документы использует первоначальный, в ожидании, примененные, сделали состояния, но вы можете использовать как многие государства вы хотите, минимум два. Поэтому, если что-то происходит во время обновления двух учетных записей, в другой части вашего приложения вы запрашиваете все ожидающие транзакции и запускаете обновления соответствующих учетных записей.

+0

Итак, какая часть делает «две фразы фиксации» особенными? –

+0

Я не касался части «двухфазной фиксации», я обновляю свой ответ. – Shanoor

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