如何在Meteor Method调用中实现事务

时间:2017-05-23 13:32:12

标签: meteor

假设我有2个收藏品" PlanSubscriptions "和" ClientActivations "。我在两个集合上连续插入。

后者取决于前一个,如果任何事务失败,那么整个操作必须回滚。

如何在Meteor 1.4中实现这一目标?

3 个答案:

答案 0 :(得分:3)

由于MongoDB不支持原子性,因此您必须使用Method Chaining进行管理。

您可以编写一个方法,例如transaction,您可以在其中调用PlanSubscriptions.insert(data, callback)。然后在回调函数中,如果第一次插入成功则调用ClientActivations.insert(data, callback1),如果第二次插入成功,则调用callback1返回truthy,否则为falsy。如果第一次插入返回错误,则您不需要执行任何操作,但如果第二次插入返回错误,则删除第一次收集中插入的ID。

我可以建议以下结构:

'transaction'(){
    PlanSubscriptions.insert(data, (error, result)=>{
        if(result){
            // result contains the _id
            let id_plan = result;
            ClientActivations.insert(data, (error, result)=>{
                if(result){
                    // result contains the _id
                    return true;
                }
                else if(error){
                    PlanSubscriptions.remove(id_plan);
                    return false;
                }
            })
        }
        else if(error){
            return false;
        }
    })
}

答案 1 :(得分:0)

在Meteor中无法做到这一点,因为mongodb不是符合ACID标准的数据库。它具有单文档更新原子性,但不是多文档更新,这是两个集合的情况。 来自mongo文档:

  

当单个写入操作修改多个文档时,每个文档的修改都是原子的,但整个操作不是原子的,其他操作可能会交错。

可以使用一种隔离多文档更新可见性的方法,但这可能不是您需要的。

  

使用$ isolated运算符,一旦写入操作修改第一个文档,影响多个文档的写入操作可以防止其他进程交错。这可确保在写入操作完成或错误输出之前,任何客户端都不会看到更改。   隔离写操作不提供“全有或全无”原子性。也就是说,写入操作期间的错误不会回滚错误之前的所有更改

但是,有几个库试图在应用级别解决问题。我建议您查看fawn

在您的情况下,如果您有两个依赖集合,则可以利用两阶段提交技术。在此处阅读更多相关信息:two-phase-commits

答案 2 :(得分:0)

我自己想通了。

我添加了一个包babrahams:transactions

在服务器端Meteor Method调用中,我调用了由包全局公开的tx对象。整个服务器端Meteor.method({})如下所示。

import { Meteor } from 'meteor/meteor';
import {PlanSubscriptions} from '/imports/api/plansubscriptions/plansubscriptions.js';
import {ClientActivations} from '/imports/api/clientactivation/clientactivations.js';

Meteor.methods({
    'createClientSubscription' (subscriptionData, clientActivationData) {
            var txid;
            try {
            txid = tx.start("Adding Subscription to our database");

            PlanSubscriptions.insert(subscriptionData, {tx: true})

            ClientActivations.insert(activation, {tx: true});

            tx.commit();

            return true;
        } catch(e){
            tx.undo(txid);
        }
        return false;
    }
});

对于我添加{tx : true}的每个插入内容,这使其成为交易的一部分。

服务器控制台输出:

I20170523-18:43:23.544(5.5)? Started "Adding Subscription to our database" with
transaction_id: vdJQvFgtyZuWcinyF
I20170523-18:43:23.547(5.5)? Pushed insert command to stack: vdJQvFgtyZuWcinyF
I20170523-18:43:23.549(5.5)? Pushed insert command to stack: vdJQvFgtyZuWcinyF
I20170523-18:43:23.551(5.5)? Beginning commit with transaction_id: vdJQvFgtyZuWcinyF
I20170523-18:43:23.655(5.5)? Executed insert
I20170523-18:43:23.666(5.5)? Executed insert
I20170523-18:43:23.698(5.5)? Commit reset transaction manager to clean state

有关详细信息,您可以转到链接:https://github.com/JackAdams/meteor-transactions

  

注意:我正在使用Meteor 1.4.4.2