From 6cee96b3508cc55d3c67d2f8fb9684657ca847a7 Mon Sep 17 00:00:00 2001 From: Matt Broadstone Date: Tue, 19 May 2020 10:18:55 -0400 Subject: [PATCH] fix: unordered bulk write should attempt to execute all batches When an unordered bulk operation is executed, it should attempt to execute all batches and only return errors after all batches have been attempted NODE-2619 --- lib/bulk/unordered.js | 8 ++++ test/functional/bulk.test.js | 72 ++++++++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/lib/bulk/unordered.js b/lib/bulk/unordered.js index 37a278370e..c126c5bbea 100644 --- a/lib/bulk/unordered.js +++ b/lib/bulk/unordered.js @@ -108,6 +108,14 @@ class UnorderedBulkOperation extends BulkOperationBase { super(topology, collection, options, false); } + + handleWriteError(callback, writeResult) { + if (this.s.batches.length) { + return false; + } + + return super.handleWriteError(callback, writeResult); + } } /** diff --git a/test/functional/bulk.test.js b/test/functional/bulk.test.js index ff13afa832..0524a67cb9 100644 --- a/test/functional/bulk.test.js +++ b/test/functional/bulk.test.js @@ -1637,9 +1637,9 @@ describe('Bulk', function() { coll.bulkWrite( [ { insertOne: { _id: 5, a: 0 } }, - { updateOne: { filter: { _id: 1 }, update: { $set: { a: 0 } } } }, + { updateOne: { filter: { _id: 1 }, update: { $set: { a: 15 } } } }, { insertOne: { _id: 6, a: 0 } }, - { updateOne: { filter: { _id: 2 }, update: { $set: { a: 0 } } } } + { updateOne: { filter: { _id: 2 }, update: { $set: { a: 42 } } } } ], { ordered: false } ) @@ -1666,7 +1666,7 @@ describe('Bulk', function() { return client.connect().then(() => { this.defer(() => client.close()); - const coll = client.db().collection('bulk_op_ordering_test'); + const coll = client.db().collection('unordered_preserve_order'); function ignoreNsNotFound(err) { if (!err.message.match(/ns not found/)) throw err; } @@ -1697,4 +1697,70 @@ describe('Bulk', function() { ); }); }); + + it('should not fail on the first error in an unorderd bulkWrite', function() { + const client = this.configuration.newClient(); + return client.connect().then(() => { + this.defer(() => client.close()); + + const coll = client.db().collection('bulk_op_ordering_test'); + function ignoreNsNotFound(err) { + if (!err.message.match(/ns not found/)) throw err; + } + + return coll + .drop() + .catch(ignoreNsNotFound) + .then(() => coll.createIndex({ email: 1 }, { unique: 1, background: false })) + .then(() => + Promise.all([ + coll.updateOne( + { email: 'adam@gmail.com' }, + { $set: { name: 'Adam Smith', age: 29 } }, + { upsert: true } + ), + coll.updateOne( + { email: 'john@gmail.com' }, + { $set: { name: 'John Doe', age: 32 } }, + { upsert: true } + ) + ]) + ) + .then(() => + coll.bulkWrite( + [ + { + updateOne: { + filter: { email: 'adam@gmail.com' }, + update: { $set: { age: 39 } } + } + }, + { + insertOne: { + document: { + email: 'john@gmail.com' + } + } + } + ], + { ordered: false } + ) + ) + .then( + () => { + throw new Error('expected a bulk error'); + }, + err => + expect(err) + .property('code') + .to.equal(11000) + ) + .then(() => coll.findOne({ email: 'adam@gmail.com' })) + .then(updatedAdam => + expect(updatedAdam) + .property('age') + .to.equal(39) + ); + }); + }); });