From 599dc13e9ef4b698ea68975eb36b0941f1bf91cf Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 9 Sep 2024 21:23:58 -0400 Subject: [PATCH] fix(transaction): avoid unnecessarily updating initial state in between transactions --- lib/plugins/trackTransaction.js | 7 ----- test/docs/transactions.test.js | 56 +++++++++++++++++++++++++++++++++ test/document.test.js | 22 ++++++------- 3 files changed, 67 insertions(+), 18 deletions(-) diff --git a/lib/plugins/trackTransaction.js b/lib/plugins/trackTransaction.js index af5c7c84da4..857caac6044 100644 --- a/lib/plugins/trackTransaction.js +++ b/lib/plugins/trackTransaction.js @@ -27,13 +27,6 @@ module.exports = function trackTransaction(schema) { initialState.atomics = _getAtomics(this); session[sessionNewDocuments].set(this, initialState); - } else { - const state = session[sessionNewDocuments].get(this); - - for (const path of Object.keys(this.$__.activePaths.getStatePaths('modify'))) { - state.modifiedPaths.add(path); - } - state.atomics = _getAtomics(this, state.atomics); } }); }; diff --git a/test/docs/transactions.test.js b/test/docs/transactions.test.js index de2ecfc9952..3dc4e33dbc7 100644 --- a/test/docs/transactions.test.js +++ b/test/docs/transactions.test.js @@ -565,6 +565,62 @@ describe('transactions', function() { assert.equal(i, 3); }); + it('transaction() avoids duplicating atomic operations (gh-14848)', async function() { + db.deleteModel(/Test/); + // Define some schemas... + const subItemSchema = new mongoose.Schema( + { + name: { type: String, required: true }, + }, + { _id: false } + ); + + const itemSchema = new mongoose.Schema( + { + name: { type: String, required: true }, + subItems: { type: [subItemSchema], required: true }, + }, + { _id: false } + ); + + const schema = new mongoose.Schema({ + items: { type: [itemSchema], required: true }, + }); + + // ...and a model + const Test = db.model("Test", schema); + + + await Test.createCollection(); + await Test.deleteMany({}); + + const { _id } = await Test.create({ + items: [ + { name: "test1", subItems: [{ name: "x1" }] }, + { name: "test2", subItems: [{ name: "x2" }] }, + ], + }); + + let doc = await Test.findById(_id); + + doc.items.push({ name: "test3", subItems: [{ name: "x3" }] }); + + let i = 0; + await db.transaction(async(session) => { + await doc.save({ session }); + if (++i < 3) { + throw new mongoose.mongo.MongoServerError({ + errorLabels: ['TransientTransactionError'] + }); + } + }); + + assert.equal(i, 3); + + doc = await Test.findById(_id); + assert.equal(doc.items.length, 3); + }); + it('doesnt apply schema write concern to transaction operations (gh-11382)', async function() { db.deleteModel(/Test/); const Test = db.model('Test', Schema({ status: String }, { writeConcern: { w: 'majority' } })); diff --git a/test/document.test.js b/test/document.test.js index d368246c133..6a5765fe116 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -8177,14 +8177,14 @@ describe('document', function() { await person.save(); }); - it('set() merge option with double nested', async function () { + it('set() merge option with double nested', async function() { const PersonSchema = new Schema({ info: { address: { city: String, - country: { type: String, default: "UK" }, + country: { type: String, default: 'UK' }, postcode: String - }, + } } }); @@ -8194,19 +8194,19 @@ describe('document', function() { const person = new Person({ info: { address: { - country: "United States", - city: "New York" - }, + country: 'United States', + city: 'New York' + } } }); - const update = { info: { address: { postcode: "12H" } } }; + const update = { info: { address: { postcode: '12H' } } }; person.set(update, undefined, { merge: true }); - - assert.equal(person.info.address.city, "New York"); - assert.equal(person.info.address.postcode, "12H"); - assert.equal(person.info.address.country, "United States"); + + assert.equal(person.info.address.city, 'New York'); + assert.equal(person.info.address.postcode, '12H'); + assert.equal(person.info.address.country, 'United States'); }); it('setting single nested subdoc with timestamps (gh-8251)', async function() {