Skip to content

Commit 9c1e548

Browse files
committed
fix(model): bump version if necessary after successful bulkSave()
Fix #15800
1 parent a5e0833 commit 9c1e548

File tree

3 files changed

+92
-9
lines changed

3 files changed

+92
-9
lines changed

lib/document.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4804,6 +4804,22 @@ Document.prototype.$clone = function() {
48044804
return clonedDoc;
48054805
};
48064806

4807+
/*!
4808+
* Increment this document's version if necessary.
4809+
*/
4810+
4811+
Document.prototype._applyVersionIncrement = function _applyVersionIncrement() {
4812+
if (!this.$__.version) return;
4813+
const doIncrement = VERSION_INC === (VERSION_INC & this.$__.version);
4814+
4815+
this.$__.version = undefined;
4816+
if (doIncrement) {
4817+
const key = this.$__schema.options.versionKey;
4818+
const version = this.$__getValue(key) || 0;// increment version if was successful
4819+
this.$__setValue(key, version + 1);
4820+
}
4821+
};
4822+
48074823
/*!
48084824
* Module exports.
48094825
*/

lib/model.js

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -417,22 +417,17 @@ Model.prototype.$__save = function(options, callback) {
417417
const versionBump = this.$__.version;
418418
// was this an update that required a version bump?
419419
if (versionBump && !this.$__.inserting) {
420-
const doIncrement = VERSION_INC === (VERSION_INC & this.$__.version);
421-
this.$__.version = undefined;
422-
const key = this.$__schema.options.versionKey;
423-
const version = this.$__getValue(key) || 0;
424420
if (numAffected <= 0) {
421+
const key = this.$__schema.options.versionKey;
422+
const version = this.$__getValue(key) || 0;
425423
// the update failed. pass an error back
426424
this.$__undoReset();
427425
const err = this.$__.$versionError ||
428426
new VersionError(this, version, this.$__.modifiedPaths);
429427
return callback(err);
430428
}
431429

432-
// increment version if was successful
433-
if (doIncrement) {
434-
this.$__setValue(key, version + 1);
435-
}
430+
this._applyVersionIncrement();
436431
}
437432
if (result != null && numAffected <= 0) {
438433
this.$__undoReset();
@@ -3663,6 +3658,8 @@ function handleSuccessfulWrite(document) {
36633658
}
36643659

36653660
document.$__reset();
3661+
document._applyVersionIncrement();
3662+
36663663
document.schema.s.hooks.execPost('save', document, [document], {}, (err) => {
36673664
if (err) {
36683665
reject(err);

test/model.test.js

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6522,7 +6522,7 @@ describe('Model', function() {
65226522
});
65236523

65246524
describe('bulkSave() (gh-9673)', function() {
6525-
it('saves new documents', async function() {
6525+
it('saves new documents', async function () {
65266526

65276527
const userSchema = new Schema({
65286528
name: { type: String }
@@ -6545,7 +6545,77 @@ describe('Model', function() {
65456545
'Hafez2_gh-9673-1'
65466546
]
65476547
);
6548+
});
6549+
6550+
it('increments version key on successful save (gh-15800)', async function() {
6551+
// Arrange
6552+
const userSchema = new Schema({
6553+
name: [String],
6554+
email: { type: String, minLength: 3 }
6555+
});
6556+
6557+
const User = db.model('User', userSchema);
6558+
const user1 = new User({ name: ['123'], email: '12314' });
6559+
await user1.save();
6560+
6561+
// Act
6562+
const user = await User.findOne({ _id: user1._id });
6563+
assert.ok(user);
6564+
6565+
// Before, __v should be 0
6566+
assert.equal(user.__v, 0);
6567+
6568+
// markModified on array field (triggers $set)
6569+
user.markModified('name');
6570+
await User.bulkSave([user]);
6571+
6572+
const dbUser1 = await User.findById(user._id);
6573+
assert.equal(dbUser1.__v, 1);
6574+
assert.equal(user.__v, 1);
6575+
6576+
// Update another path and markModified
6577+
user.email = '1375';
6578+
await User.bulkSave([user]);
6579+
const dbUser2 = await User.findById(user._id);
6580+
assert.equal(dbUser2.__v, 1);
6581+
assert.equal(user.__v, 1);
6582+
6583+
let reloaded = await User.findById(user._id);
6584+
assert.equal(reloaded.__v, 1);
6585+
6586+
user.email = '1';
6587+
await assert.rejects(
6588+
() => User.bulkSave([user]),
6589+
/email.*is shorter than the minimum allowed length/
6590+
);
6591+
assert.equal(user.__v, 1);
6592+
6593+
reloaded = await User.findById(user._id);
6594+
assert.equal(reloaded.__v, 1);
6595+
});
6596+
6597+
it('saves new documents with ordered: false (gh-15495)', async function() {
6598+
const userSchema = new Schema({
6599+
name: { type: String }
6600+
});
65486601

6602+
const User = db.model('User', userSchema);
6603+
6604+
6605+
await User.bulkSave([
6606+
new User({ name: 'Hafez1_gh-9673-1' }),
6607+
new User({ name: 'Hafez2_gh-9673-1' })
6608+
], { ordered: false });
6609+
6610+
const users = await User.find().sort('name');
6611+
6612+
assert.deepEqual(
6613+
users.map(user => user.name),
6614+
[
6615+
'Hafez1_gh-9673-1',
6616+
'Hafez2_gh-9673-1'
6617+
]
6618+
);
65496619
});
65506620

65516621
it('updates documents', async function() {

0 commit comments

Comments
 (0)