简体   繁体   中英

How to retry the mongodb transaction?

I have two different API endpoints that update the same field of a collection(wallet field of user collection). In both API transactions are implemented by using mongoose. When I hit both endpoints at the same time then one endpoint executes successfully and another one getting error of "WriteConflict" with label "TransientTransactionError".

I have read in MongoDB documentation that it provides the transaction retry functionality on the "TransientTransactionError" error. So, please suggest how to retry the transaction when I get this kind of error.

I'm receiving this error when I'm updating the same document with different endpoints at the same time.

MongoError: WriteConflict
    at Connection.<anonymous> (/Users/node_modules/mongodb-core/lib/connection/pool.js:443:61)
    at Connection.emit (events.js:196:13)
    at Connection.EventEmitter.emit (domain.js:471:20)
    at processMessage (/Users/node_modules/mongodb-core/lib/connection/connection.js:364:10)
    at TLSSocket.<anonymous> (/Users/node_modules/mongodb-core/lib/connection/connection.js:533:15)
    at TLSSocket.emit (events.js:196:13)
    at TLSSocket.EventEmitter.emit (domain.js:471:20)
    at addChunk (_stream_readable.js:290:12)
    at readableAddChunk (_stream_readable.js:271:11)
    at TLSSocket.Readable.push (_stream_readable.js:226:10)
    at TLSWrap.onStreamRead (internal/stream_base_commons.js:166:17) {
  errorLabels: [ 'TransientTransactionError' ],
  operationTime: Timestamp { _bsontype: 'Timestamp', low_: 2, high_: 1591772061 },
  ok: 0,
  errmsg: 'WriteConflict',
  code: 112,
  codeName: 'WriteConflict',
  '$clusterTime': {
    clusterTime: Timestamp { _bsontype: 'Timestamp', low_: 2, high_: 1591772061 },
    signature: { hash: [Binary], keyId: [Long] }
  },
  name: 'MongoError',
  [Symbol(mongoErrorContextSymbol)]: {}
}

Thanks in advance

The documentation provides examples of how to properly use transactions. Click on "nodejs" to see the node examples.

The withTransaction function in the driver implements the retry functionality.

You can implement a function that retries the transaction when a commit error occurs:

const commitWithRetry = async (session) => {
  for (;;) {
    try {
      await session.commitTransaction();
      session.endSession();
      break;
    } catch (error) {
      const isTransientError = Object.prototype.hasOwnProperty.call(error, 'errorLabels')
          && error.errorLabels.includes('UnknownTransactionCommitResult');
      if (!isTransientError) {
        throw error;
      }
    }
  }
};

To commit with retries, invoke the function on your session object:

await commitWithRetry(session);

Hope this helps.

EDIT: I'm unaware why this answer was downvoted but to provide added context, an example of this approach's usage can be found in the MongoDB documentation here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM