Reputation: 2954
I'm new to sequelize right now I'm a bit confused how to use the transactions of sequelize.
My project launches events that can be called at the same time,here is a minimized example with two events, eventA or eventB, and a minimized model User.
var Sequelize = require('sequelize');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('Uer', {
stuff: {
type: Sequelize.STRING,
defaultValue: ""
}
}, {
classMethods: {
getAllUsers : function (resultsCallback) {
this.findAll().complete(function(err, users) {
resultsCallback(err, users);
})
}
},
instanceMethods: {
update1: function (transaction) {
var stuff = this.stuff + "1";
this.updateUserAttributes(document, transaction, function(err, results){
});
},
update2: function (transaction) {
var stuff = this.stuff + "2";
var document = {};
document.stuff = stuff;
this.updateUserAttributes(document, transaction, function(err, results){
});
},
updateUserAttributes : function(document, transaction, resultsCallback) {
var docArray = [];
var call = _.after(Object.keys(document).length, function(){
this
.updateAttributes(document, docArray, {
transaction: transaction
})
.complete(function(err, results) {
if (!!err) {
console.log('An error occurred while updating', err)
} else if (!results) {
console.log('Failed to update User.')
}
resultsCallback(err, results);
});
}.bind(this));
for(var key in document){
docArray.push(String(key));
call();
}
}
}
});
}
eventA
...
sequelize.transaction(function(transaction) {
User.sync().success(function(err, restuls){
User.getAllUsers(function(err, results){
for (var i = 0; i < results.length; i++){
results[i].update1(transaction)
}
transaction.commit();
});
});
});
...
eventB
....
sequelize.transaction(function(transaction) {
User.sync().success(function(err, restuls){
User.getAllUsers(function(err, results){
for (var i = 0; i < results.length; i++){
results[i].update2(transaction)
}
transaction.commit();
});
});
});
...
My problem is, for example the first occurrence of events A and B are called but only one of them remains in the DB sutff = "2" instead of stuff = "12".
Upvotes: 1
Views: 6797
Reputation: 2954
Just to others that have the same problem. I ended up solving this with a row locking.
Also I wasn't passing the transaction to all .save()
and .updateAttributtes()
, as well as I wasn't using the update attributes correctly, that is (at least for what I saw):
updateAttributes({fieldName: newFieldValue}, {fields:[fieldName], transaction:transaction})
Upvotes: 1
Reputation: 2545
Here is my implementation and use this method everywhere.
function trans(callback, done) {
sequelize.transaction(function (t) {
function commit(callback) {
t.commit().done(function (err) {
console.log('commited')
if (callback)
callback(err)
})
}
function rollback(rollbackErr, callback) {
t.rollback().done(function (err) {
if (callback)
callback(err || rollbackErr)
})
}
t.done(function () {
if (done) done()
})
callback(commit, rollback, t)
})
}
function someExecution(data, callback){
trans(function(commit, rollback, t){
Model.create(data, {transaction: t}).done(function(err, obj){
if (err) return rollback(err, callback)
Model.findAll({where: {some: 1}}, {transaction: t}).done(function(err, list){
if (err) return rollback(err, callback)
commit(callback)
})
})
})
}
Upvotes: 1