We've been trying to implement ACID transactions in Loopback without success. The only examples in the documentation use the 'create' method.We've tried completely overriding the events as well as multiple variations of Operation Hooks. We have only been able to get the create example to work.
Core Requirement: We need to be able to start a transaction in the create and update methods for a specific model and then update multiple tables in the transaction (either using Loopback's ORM functions or directly with SQL) with the ability to commit or rollback based on business rules. For example, we need the end-point to be able to accept an invoice with its header and detail transactions, validate it, update various tables (such as inventory and customer) and then save (or rollback) all of the changes in one single ACID transaction.
Using Database Transactions: https://docs.strongloop.com/display/public/LB/Using+database+transactions)
Here's the example from the documentation:
Post.create({title: 't1', content: 'c1'}, {transaction: tx}, function(err, post) {
post.updateAttributes({content: 'c2', {transaction: tx}, function(err, newPost) {
//
newPost.reviews.create({content: 'r1'}, {transaction: tx}, function(err, newPost) {
});
}
});
Operation Hooks: https://docs.strongloop.com/display/public/LB/Operation+hooks
We were only able to successfully override a few of the core methods:
Item.create = function(id, cb){
console.log('create'); // Success!
}
//
Item.find = function(id, cb){
console.log('find'); // Success!
}
Item.findById = function(id, cb){
console.log('findById'); // Success!
}
Item.getById = function(id, cb){
console.log('updateAttributes'); // Did not work!
}
Item.all = function(id, cb){
console.log('all'); // Did not work!
};
Item.findOrCreate = function(id, test, cb){
console.log('findOrCreate'); // Did not work!
}
Item.replicate = function(id, test, cb){
console.log('replicate'); // Did not work!
}
Item.save = function(id, test, cb){
console.log('save'); // Did not work!
}
Item.updateAll = function(id, test, cb){
console.log('updateAll'); // Did not work!
}
Item.upsert = function(id, test, cb){
console.log('upsert'); // Did not work!
}
Item.updateAttribute = function(id, cb){
console.log('updateAttribute'); // Did not work!
};
Item.updateById = function(id, test, cb){
console.log('updateById'); // Did not work!
}
Implementing save, update, etc in operational hooks did not work either:
Item.observe('before save', function(ctx, next) {
console.log('before save');
ctx.Model.beginTransaction({isolationLevel: ctx.Model.Transaction.READ_COMMITTED}, function(err, tx) {
// Now we have a transaction (tx)
console.log('begin transaction', err);
//tx.commit(function(err) {
// console.log('commit', err);
//})
//tx.rollback(function(err) {
// console.log('rollback', err);
//})
next();
});
})