[Solved] Mongo client and session to create a transaction

Hello there,

I’ve read in this blog article https://blog.meteor.com/meteor-1-8-erases-the-debts-of-1-7-77af4c931fe3 that meteor now is able to get mongo’s transaction oplog correctly…
But how can I use this transactions in the first place? How can I access a mongo client to start a session and make updates to multiple collections atomic?

Somehow I’m not able to use google correctly to get an answer, so I thought I ask you. :smiley:

I hope you can help me.

1 Like

This may help:

1 Like

Whoa! Thank you for the fast help! :0D That’s great! I will take a look instantly! :0D

1 Like

Thank you a lot! Creating a Transaction works like a charm now. :0D I’m just to dump to use it correctly.

I tried to test it the following way:

const client = Meteor.users._driver.mongo.client;
let session = await client.startSession();

session.startTransaction();

Collection1.update(find, {$set}, function(error){
    if(error){
        session.abortTransaction();
        return;
    }

    try {
        let newObject = {foo: bar};

        throw "This is an exception!";

        Collection2.insert(newObject, function(error){
            if(error){
                session.abortTransaction();
            }else{
                session.commitTransaction();
            }
        });
    }catch(exception){
        session.abortTransaction();
    }
});

My problem is, that even if I throw that error and do the abortTransaction method, the entry in collection1 will be made…

I know I have to connect the update and the insert call to the session but I don’t know how… Do I have to use the raw collection to achieve this, or can I use the Meteor collection with some parameters?

Hi @ruerob,

Your issue is in ussing the Collection and not the rawCollection. Meteor collections doesnt support transactions yet. So your code will looks like this.

const client = Meteor.users._driver.mongo.client;
const session = await client.startSession();

session.startTransaction();
const options = { session };

try {
 const res1 = await Collection1.rawCollection().updateOne(find, {$set}, options);

 const newObject = {foo: bar};

 const res2 = await Collection2.rawCollection().insert(newObject, options);

 session.commitTransaction();
} catch (error) {
 session.abortTransaction();
}

Let me know if that helps you.

2 Likes

I would also use MongoInternals instead of the private property ._driver your are using.

import { MongoInternals } from 'meteor/mongo';


const { client } = MongoInternals.defaultRemoteCollectionDriver().mongo;

...
1 Like

Thank you for the help! Now everything works as it should. :smile:

1 Like