如何在环回中实施ACID事务 [英] How To Implement ACID Transactions in Loopback

查看:116
本文介绍了如何在环回中实施ACID事务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们一直在尝试在Loopback中实现ACID事务,但没有成功.本文档中仅有的示例使用'create'方法.我们尝试完全覆盖事件以及操作挂钩的多个变体.我们只能使创建示例起作用.

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.

核心要求:我们需要能够在特定模型的创建和更新方法中启动事务,然后在事务中更新多个表(使用Loopback的ORM函数或直接使用SQL ),并具有根据业务规则进行提交或回滚的能力. 例如,我们需要端点能够接受带有抬头和明细交易的发票,进行验证,更新各种表(例如库存和客户),然后保存(或回滚)一次ACID交易中的所有更改.

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.

使用数据库事务: https://docs.strongloop.com/display/public/LB/使用+数据库+交易)

这是文档中的示例:

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

操作挂钩: 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();
    });
})

推荐答案

我设法使事务正常运行,但是我不知道这是否是最好的方法. 我需要检查实例",因为当找不到用户时,它不会返回错误,但是实例为null.我使用内置的promise来做到这一点,因为使用回调真的很丑.

I've managed to get a transaction working, but I don't know if this is the best way of doing it. I needed to check the "instance" because when the user is not found it does not return an error, but the instance is null. I did it using the built-in promises, because it would be really ugly using callbacks.

在下面的示例中,我必须找到两个用户才能更新两个用户.仅当两个值都被修改时,事务才应该成功.如果在此期间发生一个错误,则应停止事务(回滚).

In the following example I had to find two users in order to update both of them. The transaction should succeed only if both values where modified. If one error occurred in the meantime, the transaction should be stopped (rolledback).

var firstUserInstance;
var secondUserInstance;

User.beginTransaction('READ COMMITTED', function(err, tx) {
      // find first user and pass it to first 'then'
      User.findById(firstUser.userId, {transaction: tx})
        .then(function(instance){
            if(instance){
                firstUserInstance = instance;
                //Pass second user instance to next 'then'
                return User.findById(firstUser.userId, {transaction: tx});
            }else{
                throw ({message: "User not found", status: 400});
            }
        })
        // Update first user
        .then(function(instance){
            if(instance){
                secondUserInstance = instance;
                //Update first user and pass result to next 'then'
                return firstUserInstance.updateAttribute("attribute", "newValue", {transaction: tx});
            }else{
                throw ({message: "User 'toUserId' not found", status: 400});
            }

        })
        // Update second user
        .then(function(instance){
            if(instance){
                //Update second user and pass result to next 'then'
                return secondUserInstance.updateAttribute("attribute", "newValue", {transaction: tx});
            }else{
                throw ({message: "Error updating", status: 401});
            }
        })
        .then(function(instance){
            if(instance){
                //Everything went OK - commit changes
                console.log(instance);
                tx.commit(function(err){});
            }else{
                throw ({message: "Error updating", status: 401});
            }

        })
        .catch(function(err){
            //Something happened - Any thrown errors will end here - rollback changes
            console.log(err);
            tx.rollback(function(err){});
        });

    });

我对此并不完全满意,我认为还有更好的方法,但是我希望这会有所帮助!

I am not completely happy with this, I think there is still a better way of doing it, but I hope this helps!

这篇关于如何在环回中实施ACID事务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆