Unmanaged transactions, CLS and tests
See original GitHub issueGood day. This is a duplication of https://github.com/sequelize/sequelize/issues/3888 with some extended examples.
version
== 3.4.1
So, here is basic setup:
- Application, that uses
sequelize
transactions and create instance of db like:
const createDb = (conf, namespaceName='my-super-personal-namespace') => {
const {uri} = conf;
const namespace = cls.createNamespace(cls);
Sequelize.cls = namespace;
const options = Object.assign({}, conf); // Sequelize doesn't work with frozen
const sequelize = new Sequelize(uri, options);
const Thing = sequelize.import('./thing');
return {
sequelize,
Thing,
_namespace: namespace
};
};
- And here goes a test:
let db;
let transaction;
before(() => {
db = createDb(config);
return db.sequelize.sync();
});
beforeEach(() => db.sequelize
.transaction({autocommit: false})
.then(t => {
transaction = t;
}));
afterEach(() => transaction.rollback());
after(() => db.sequelize.drop());
it('should create instance of Thing', () => {
return db.Thing.create({
name: 'foo'
}, {transaction}).then(thing => { // FIXME: bad for tests
expect(thing.id).to.be.a('number');
expect(thing.name).to.be.eql('foo');
});
});
This code works but it requires manual pass of transaction
.
I’ve expected that following code would work, but it fails in afterEach
:
let db;
before(() => {
db = createDb(config);
return db.sequelize.sync();
});
beforeEach(() => db.sequelize
.transaction({autocommit: false})
.then(t => {
db._namespace.set('transaction', t);
}));
afterEach(() => db._namespace.get('transaction').rollback());
after(() => db.sequelize.drop());
it('should create instance of Thing', () => {
return db.Thing.create({
name: 'foo'
}).then(thing => {
expect(thing.id).to.be.a('number');
expect(thing.name).to.be.eql('foo');
});
});
Could you advice please what is a best way to solve this issue?
Thank you!
Issue Analytics
- State:
- Created 8 years ago
- Comments:17 (8 by maintainers)
Top Results From Across the Web
How to use cls-hooked unmanaged transactions?
I'm writing tests with jest and sequelize and I need to keep my database clean for every test, so I want to set...
Read more >Use CLS with Sequelize Unmanaged transactions-node.js
[Solved]-Use CLS with Sequelize Unmanaged transactions-node.js ... This is tricky for tests because describe() calls can be nested and each can have their ......
Read more >Transactions - Sequelize
Sequelize supports two ways of using transactions: Unmanaged transactions: Committing and rolling back the transaction should be done manually by the user ...
Read more >Managed transaction (auto-callback) - Manual | Sequelize
The key difference is that the managed transaction uses a callback that expects a promise to be returned to it while the unmanaged...
Read more >Handling Nested Db Transactions using CLS - Medium
One of the ways we could solve this is bypassing the Transaction Object from parent to child. We can then use the same...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
If I read your code correctly, this is never going to work with CLS. The transaction is only available in the
then
callback:But nothing is done in that callback - after it finished, then context is cleared, because that callback / promise chain ends.
Thing.create
should be called from inside the callback:You can also do it slightly more succinctly, by using a managed transaction
Update:
My code with
CLS
can be done like this and it would work, but it is not so ideal.