I'm currently playing with transactions in latest available docker image of MongoDB 4.1.4 (using Node 8.12.0 and Mongoose 5.3.8 as client). I've made a simple replica set with 3 mongo instances, everything works fine and all until I do a lot of WriteConflict errors during short time.
My code looks like this:
// name, value are strings // date is current time const session = await createAnalyticsTransaction(); // returns 'session' // _id is pregenerated var stat = await Logger.findById(_id).session(session); if (stat) { // do nothing if it already exists return true; } await Logger.update({ _id }, { $setOnInsert: { _id, name, created: date.toDate(), modified: date.toDate() } }, { session, upsert: true }); /* var period = 'month'; var time = '2018-11'; await Analytics.update({ _id }, { $setOnInsert: { _id, name, period, time, created: date.toDate() }, $inc: inc }, { upsert: true, session: session }); */ await session.commitTransaction(); await session.endSession(); Everything works here so far until I uncomment an upsert into Analytics collection with $inc and $setOnInsert and run about 1000 simultaneous operations. The idea is that Analytics collection should be created if it wasn't created yet. And then I start getting a lot of MongoError: WriteConflict, with error's property errorLabels having TransientTransactionError.
I assume it's because of $inc or upsert: true? Did anyone experience this? What's the best solution in this case?
{ MongoError: WriteConflict at /Users/akuzmenok/Zend/MeteorLingua/lingua-analytics/node_modules/mongodb-core/lib/connection/pool.js:581:63 at authenticateStragglers (/Users/akuzmenok/Zend/MeteorLingua/lingua-analytics/node_modules/mongodb-core/lib/connection/pool.js:504:16) at Connection.messageHandler (/Users/akuzmenok/Zend/MeteorLingua/lingua-analytics/node_modules/mongodb-core/lib/connection/pool.js:540:5) at emitMessageHandler (/Users/akuzmenok/Zend/MeteorLingua/lingua-analytics/node_modules/mongodb-core/lib/connection/connection.js:310:10) at Socket.<anonymous> (/Users/akuzmenok/Zend/MeteorLingua/lingua-analytics/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 (/Users/akuzmenok/.meteor/packages/promise/.0.11.1.1ugu6ow.mjjhg++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/meteor-promise/promise_server.js:56:12) at Promise.asyncApply (imports/lib/analytics.js:97:9) at /Users/akuzmenok/.meteor/packages/promise/.0.11.1.1ugu6ow.mjjhg++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/meteor-promise/fiber_pool.js:43:40 => awaited here: at Function.Promise.await (/Users/akuzmenok/.meteor/packages/promise/.0.11.1.1ugu6ow.mjjhg++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/meteor-promise/promise_server.js:56:12) at Promise.asyncApply (imports/lib/analytics.js:139:5) at /Users/akuzmenok/.meteor/packages/promise/.0.11.1.1ugu6ow.mjjhg++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/meteor-promise/fiber_pool.js:43:40 => awaited here: at Function.Promise.await (/Users/akuzmenok/.meteor/packages/promise/.0.11.1.1ugu6ow.mjjhg++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/meteor-promise/promise_server.js:56:12) at Promise.asyncApply (imports/lib/analytics.js:158:5) at /Users/akuzmenok/.meteor/packages/promise/.0.11.1.1ugu6ow.mjjhg++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/meteor-promise/fiber_pool.js:43:40 => awaited here: at Function.Promise.await (/Users/akuzmenok/.meteor/packages/promise/.0.11.1.1ugu6ow.mjjhg++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/meteor-promise/promise_server.js:56:12) at Promise.asyncApply (imports/lib/analytics.js:49:23) at /Users/akuzmenok/.meteor/packages/promise/.0.11.1.1ugu6ow.mjjhg++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/meteor-promise/fiber_pool.js:43:40 => awaited here: at Function.Promise.await (/Users/akuzmenok/.meteor/packages/promise/.0.11.1.1ugu6ow.mjjhg++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/meteor-promise/promise_server.js:56:12) at Promise.asyncApply (imports/lib/analytics.js:14:23) at /Users/akuzmenok/.meteor/packages/promise/.0.11.1.1ugu6ow.mjjhg++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/meteor-promise/fiber_pool.js:43:40 errorLabels: [ 'TransientTransactionError' ], operationTime: Timestamp { _bsontype: 'Timestamp', low_: 12, high_: 1541424838 }, ok: 0, errmsg: 'WriteConflict', code: 112, codeName: 'WriteConflict', '$clusterTime': { clusterTime: Timestamp { _bsontype: 'Timestamp', low_: 12, high_: 1541424838 }, signature: { hash: [Object], keyId: 0 } }, name: 'MongoError', [Symbol(mongoErrorContextSymbol)]: {} } Another note, I'm starting a transaction like this:
const session = await MongoAnalytics.startSession({ causalConsistency: true }); session.startTransaction({ readConcern: { level: 'snapshot' }, writeConcern: { w: 'majority' } }); 