如何重试 mongodb 交易?
How to retry the mongodb transaction?
我有两个不同的 API 端点更新集合的相同字段(用户集合的钱包字段)。在这两个 API 中,事务都是通过使用 mongoose 实现的。当我同时点击两个端点时,一个端点成功执行,另一个端点出现 "WriteConflict" 错误,标签为 "TransientTransactionError".
我在 MongoDB 文档中读到它提供了针对 "TransientTransactionError" 错误的事务重试功能。所以,请建议我遇到这种错误时如何重试交易。
当我同时使用不同端点更新同一文档时收到此错误。
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)]: {}
}
提前致谢
您可以实现一个在发生提交错误时重试事务的函数:
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;
}
}
}
};
要提交重试,请在您的会话对象上调用该函数:
await commitWithRetry(session);
希望对您有所帮助。
编辑:
我不知道为什么这个答案被否决了,但为了提供更多的上下文,可以在 MongoDB 文档 here.
中找到这种方法的用法示例
有关如何正确使用事务的文档 provides examples。单击 "nodejs" 查看节点示例。
驱动中的withTransaction
函数实现了重试功能。
我有两个不同的 API 端点更新集合的相同字段(用户集合的钱包字段)。在这两个 API 中,事务都是通过使用 mongoose 实现的。当我同时点击两个端点时,一个端点成功执行,另一个端点出现 "WriteConflict" 错误,标签为 "TransientTransactionError".
我在 MongoDB 文档中读到它提供了针对 "TransientTransactionError" 错误的事务重试功能。所以,请建议我遇到这种错误时如何重试交易。
当我同时使用不同端点更新同一文档时收到此错误。
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)]: {}
}
提前致谢
您可以实现一个在发生提交错误时重试事务的函数:
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;
}
}
}
};
要提交重试,请在您的会话对象上调用该函数:
await commitWithRetry(session);
希望对您有所帮助。
编辑: 我不知道为什么这个答案被否决了,但为了提供更多的上下文,可以在 MongoDB 文档 here.
中找到这种方法的用法示例有关如何正确使用事务的文档 provides examples。单击 "nodejs" 查看节点示例。
驱动中的withTransaction
函数实现了重试功能。