Mongo Transactions throwing WriteConflict when using a for loop

#1

Hello, we are trying to incorporate transactions to our backend system, Meteor doesn’t natively support mongo 4.x transactions so we are using the mongo driver directly and a separate instance of mongodb running 4.0.6 that get connect our backend to.

We are getting some WriteConflicts errors when trying to update docs on a simple for loop, we aren’t updating same docs, all are different but each time we step onto that function we get the same error “WriteConflict” labeled as “TransientTransactionError”

MongoError: WriteConflict     at /home/luismexin/.meteor/packages/npm-mongo/.3.1.1.kuc460.vefy++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/mongodb-core/lib/connection/pool.js:581:63     at authenticateStragglers (/home/luismexin/.meteor/packages/npm-mongo/.3.1.1.kuc460.vefy++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/mongodb-core/lib/connection/pool.js:504:16)     at Connection.messageHandler (/home/luismexin/.meteor/packages/npm-mongo/.3.1.1.kuc460.vefy++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/mongodb-core/lib/connection/pool.js:540:5)     at emitMessageHandler (/home/luismexin/.meteor/packages/npm-mongo/.3.1.1.kuc460.vefy++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/mongodb-core/lib/connection/connection.js:310:10)     at Socket.<anonymous> (/home/luismexin/.meteor/packages/npm-mongo/.3.1.1.kuc460.vefy++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/mongodb-core/lib/connection/connection.js:453:17)     at emitOne (events.js:116:13)     at Socket.emit (events.js:211:7)     at addChunk (_stream_readable.js:263:12)     at readableAddChunk (_stream_readable.js:250:11)     at Socket.Readable.push (_stream_readable.js:208:10)     at TCP.onread (net.js:597:20)  => awaited here:     at Function.Promise.await (/home/luismexin/.meteor/packages/promise/.0.11.2.rhsamv.6ocp++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/meteor-promise/promise_server.js:56:12)     at Promise.asyncApply (server/methods/update/updateKits.js:314:32)     at /home/luismexin/.meteor/packages/promise/.0.11.2.rhsamv.6ocp++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/meteor-promise/fiber_pool.js:43:40 

Example Code:

async function loopUpdate(ids, length, mongoSession){ 
    try {         
        for (const id of ids) {             
            await CollectionRaw.update({ numKit: id }, { $inc: { total: length } }, { session: mongoSession });         
        }     
    } catch(e) {         
        console.error(e);     
} } 

we start the transaction when invoking the main function and pass the mongo session down several functions we call, when we step into the loop it always breaks.

I’ve already tried using an async queue but when finishing the queue the transaction gets aborted. so I’m really lost on where and why the error is coming from.

Thanks

1 Like
#2

TransientTransactionError is one of typically possible problems that can occur in the lifetime of a transaction and is one that is recoverable simply by retrying. In fact, this is so common that official docs provide extensive examples around this and other seemingly possible scenarios.

https://docs.mongodb.com/manual/core/transactions/#retry-transaction

There’s another example further down the page that cover more cases, though you should also add general checks around the whole logic that guards your application against any final error outcome and manages the overall error case gracefully.

2 Likes