New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transaction autocommit setting ignored when using findOrCreate #2418

Closed
sheltond opened this Issue Oct 14, 2014 · 4 comments

Comments

5 participants
@sheltond
Contributor

sheltond commented Oct 14, 2014

When I create a transaction with options { autocommit: false } and then do a findOrCreate within that transaction, the nested transaction created by findOrCreate uses the default value for autocommit (true) and overwrites the autocommit setting originally set up for the transaction.

I get the following sequence of operations:

(2dbbc30f-5417-4e44-a4dd-03274c31b642): START TRANSACTION;
(2dbbc30f-5417-4e44-a4dd-03274c31b642): SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
(2dbbc30f-5417-4e44-a4dd-03274c31b642): SET autocommit = 0;
(2dbbc30f-5417-4e44-a4dd-03274c31b642): SAVEPOINT 2dbbc30f-5417-4e44-a4dd-03274c31b642-savepoint-1;
(2dbbc30f-5417-4e44-a4dd-03274c31b642): SET autocommit = 1;

and then it goes on to do the select, insert, etc.

I notice that it doesn't issue a duplicate SET SESSION TRANSACTION ISOLATION LEVEL command for the inner transaction - there is logic in lib/dialects/abstract/query-generator.js to prevent this, but there is no equivalent for the autocommit.

@mickhansen mickhansen added the bug label Oct 14, 2014

@jbarros35

This comment has been minimized.

jbarros35 commented Jun 28, 2015

I have same problem here.

sequelize.transaction({autocommit: false}, function (t) {       

        return models.post.build().updateAttributes({
                title: req.body.title,
                shortdescription: req.body.description.substring(0,255),
                description: req.body.description,
                titleImage: req.body.titleImage, 
                link: req.body.link,
                userid: req.body.userid 
            }, {transaction: t}).then(function(post){
                newpost = post; 
                // create categories
                var tags = req.body.categories;

                models.hashtag.bulkCreate(tags, {transaction: t}).then(function(){
                    newpost.setTags(tags, {transaction: t});
                });         
        });


    }).then(function (result) {
        // Transaction has been committed
        // result is whatever the result of the promise chain returned to the transaction callback is
        if (newpost) {
            res.json(newpost);
        }
        console.log(result);
    }).catch(function (e) {
        // Transaction has been rolled back
        // err is whatever rejected the promise chain returned to the transaction callback is
        throw e;
    });

Executing (c457e532-b164-43dc-9b0e-432be031fe36): START TRANSACTION;
Executing (c457e532-b164-43dc-9b0e-432be031fe36): SET SESSION TRANSACTION ISOLAT
ION LEVEL REPEATABLE READ;
Executing (c457e532-b164-43dc-9b0e-432be031fe36): INSERT INTO "posts" ("title","
shortdescription","description","updatedAt","createdAt") VALUES ('hero one','her
o one','hero one','2015-06-28 20:40:48.989 +00:00','2015-06-28 20:40:48.989 +00:
00') RETURNING *;
Executing (c457e532-b164-43dc-9b0e-432be031fe36): COMMIT;
Executing (c457e532-b164-43dc-9b0e-432be031fe36): INSERT INTO "hashtags" ("hashI
d","description","createdAt","updatedAt") VALUES (DEFAULT,'abc','2015-06-28 20:4
0:48.989 +00:00','2015-06-28 20:40:48.989 +00:00'),(DEFAULT,'def','2015-06-28 20
:40:48.989 +00:00','2015-06-28 20:40:48.989 +00:00'),(DEFAULT,'ghij','2015-06-28
20:40:48.989 +00:00','2015-06-28 20:40:48.989 +00:00');

Crap! I don't want having a commit after insert into posts, I want a commit after insert to hashtags and everything is allright why such simple thing can be so hard?

@jbarros35

This comment has been minimized.

jbarros35 commented Jun 28, 2015

POST /api/posts/ 200 38.196 ms - 231
Unhandled rejection Error: commit has been called on this transaction(c457e532-b
164-43dc-9b0e-432be031fe36), you can no longer use it

@janmeier

This comment has been minimized.

Member

janmeier commented Jun 28, 2015

@jbarros35 You need to return models.hashtag.bulkCreate and return newpost.setTags

You are using a managed transaction (http://docs.sequelizejs.com/en/latest/docs/transactions/#managed-transaction-auto-callback), which means that the transaction will be committed when the promise chain has been resolved.

If you do something async (such as hashtag.bulkCreate) you need to return the promise, so sequelize can wait for the promise to be resolved.

Please read up on promise flow: https://github.com/petkaantonov/bluebird/blob/master/API.md and https://www.promisejs.org/

@srinivasrk

This comment has been minimized.

srinivasrk commented Sep 19, 2018

I have similar problem when I run transaction.commit() I get the error Error: commit has been called on this transaction
I cannot even catch the error or handle it gracefully

The only difference is I am using unmanaged transaction

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment