我正在尝试使用事务来更新多个文档。
一种是加载表单文档 [await Sheet.save({ session });]
另一个是库存预订记录数组 [await Stock.bulkWrite()]。
const session = await mongoose.startSession();
session.startTransaction({
readPreference: 'primary',
readConcern: { level: 'local' },
writeConcern: { w: 'majority' },
});
let sheetAfterSave: any = null;
try {
sheetAfterSave = await sheet.save({ session });
records.forEach(async (el: any) => {
let updatedStockRecord = await Stock.bulkWrite(
[
{
updateOne: {
filter: {
index: el.index,
product: el.product,
batchNo: el.batchNo,
agency,
totalQuantity: { $gte: el.loadingTotal },
},
update: {
$push: {
reservations: {
loadingSheetId: sheetAfterSave._id,
reservedCaseQuantity: el.loadingCaseCount,
reservedUnitQuantity: el.loadingUnitCount,
reservedTotalQuantity: el.loadingTotal,
},
},
},
},
},
],
{
session: session,
}
);
});
await session.commitTransaction();
session.endSession();
} catch (error) {
console.log(error);
await session.abortTransaction();
session.endSession();
throw new Error(
`Error occured while trying to create a new loading sheet. ${error}`
);
}
在此操作中,加载表文档保存在数据库中,但不保存在库存预订记录数组中。
它给出了错误
[distribution] MongoError: Transaction 1 has been committed.
[distribution] at MessageStream.messageHandler (/app/node_modules/mongoose/node_modules/mongodb/lib/cmap/connection.js:263:20)
[distribution] at MessageStream.emit (node:events:376:20)
[distribution] at processIncomingData (/app/node_modules/mongoose/node_modules/mongodb/lib/cmap/message_stream.js:144:12)
[distribution] at MessageStream._write (/app/node_modules/mongoose/node_modules/mongodb/lib/cmap/message_stream.js:42:5)
[distribution] at writeOrBuffer (node:internal/streams/writable:388:12)
[distribution] at MessageStream.Writable.write (node:internal/streams/writable:333:10)
[distribution] at TLSSocket.ondata (node:internal/streams/readable:716:22)
[distribution] at TLSSocket.emit (node:events:376:20)
[distribution] at addChunk (node:internal/streams/readable:305:12)
[distribution] at readableAddChunk (node:internal/streams/readable:280:9)
[distribution] at TLSSocket.Readable.push (node:internal/streams/readable:219:10)
[distribution] at TLSWrap.onStreamRead (node:internal/stream_base_commons:192:23)
[distribution] [ERROR] 14:56:43 MongoError: Transaction 1 has been committed.
当我在这样的失败中使用会话时,必须回滚保存的文档,但这里没有发生这种情况。
我在这里错过了什么吗?感谢你的帮助
Cheers
你看到这段代码有什么问题吗?我试图在循环内创建一个动态错误,以确保如果循环内发生任何错误,所有事务都会回滚?循环外的动态错误会完美回滚所有事务,但不会回滚循环内的事务。
const session = await mongoose.startSession();
try {
await session.withTransaction(
async () => {
sheetAfterSave = await sheet.save({ session });
records.forEach(async (el: any) => {
let updatedStockRecord = await Stock.bulkWrite(
[
{
updateOne: {
filter: {
index: el.index,
product: el.product,
batchNo: el.batchNo,
agency,
totalQuantity: { $gte: el.loadingTotal },
},
update: {
$push: {
reservations: {
loadingSheetId: sheetAfterSave._id,
reservedCaseQuantity: el.loadingCaseCount,
reservedUnitQuantity: el.loadingUnitCount,
reservedTotalQuantity: el.loadingTotal,
},
},
},
},
},
],
{
session: session,
}
);
console.log('******************');
throw new Error('12/24/2020 ERROR INSIDE LOOP'); // MongoError: Transaction 1 has been committed.
});
throw new Error('12/24/2020 ERROR OUTSIDE LOOP'); // All transactions are rolled back perfectly
},
{
readPreference: 'primary',
readConcern: { level: 'local' },
writeConcern: { w: 'majority' },
}
);
} catch (error) {
console.log('ERROR BLOCK', error);
throw new Error(
`Error occured while trying to create a new loading sheet. ${error}`
);
} finally {
session.endSession();
await mongoose.connection.close();
console.log('************ FINALLY *****************');
}