Question

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".

Was it helpful?

Solution 2

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})

OTHER TIPS

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)
            })
        })
    })

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top