Reputation: 4805
Say that I am developing the back-end for a Polling app. The user selects an option in a poll and a request to update both the poll document and the users document is made.
// Express endpoint for /vote/:pollId/:optionIndex
// (middleware puts users document on req.user)
function(req, res) {
//Check if the user has already voted on this poll
...
Polley.findByIdAndUpdate(req.params.pollId, {
//increment the number of votes on the selected options by one
$inc: ...
}, {
new: true
}, function (err, data) {
//If err send error message
...
// Now update the users document, so that the user
// can't vote on this poll again and so the user can go
// back and see what he/she voted for.
User.findByIdAndUpdate( req.user._id,
{
$push: {
votes: {
polleyId: req.params.polleyId,
optionIndex: req.params.optionIndex
}
}
},
function (err, user) {
// HERE IS THE PROBLEM.
// what if error happens here? Then the user will be able
// to vote on this poll one more time since the vote was not
// successfully saved in the users document.
}
);
res.status(200).json({ poll_votes: data.votes, message: "Vote Successful." });
});
}
I removed parts with ...
because the implementation is not relevant to the question.
Both of these operations need to be made in one call so that the user does not have the power to only update the poll document but not the user document.
The problem, as i stated as a comment in the code, is that if i first update the poll document and afterwards update the user document, the first operation could be successful while the second is not.
How do I ensure that both operations either fails or succeeds?
Upvotes: 0
Views: 101
Reputation: 1003
MongoDB doesn't support atomic update of different collections and transactions. To answer your question I see two approaches:
patching way
that allows you make atomic operations (like Google Docs does).nodejs
in which using Tokumx for this purpose not possible due transactions are associated with a thread.If you need to support transactions and need to use MongoDB I would advice to try Two Phase Commits
because it's simplest way to resolve your task.
Upvotes: 1