Skip to content

Commit a8a2a14

Browse files
authored
Merge pull request #15809 from Automattic/vkarpov15/gh-15800
fix(model): bump version if necessary after successful bulkSave()
2 parents 1405e4f + 7a305a8 commit a8a2a14

File tree

3 files changed

+68
-8
lines changed

3 files changed

+68
-8
lines changed

lib/document.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5422,6 +5422,22 @@ Document.prototype.$__hasOnlyPrimitiveValues = function $__hasOnlyPrimitiveValue
54225422
}));
54235423
};
54245424

5425+
/*!
5426+
* Increment this document's version if necessary.
5427+
*/
5428+
5429+
Document.prototype._applyVersionIncrement = function _applyVersionIncrement() {
5430+
if (!this.$__.version) return;
5431+
const doIncrement = VERSION_INC === (VERSION_INC & this.$__.version);
5432+
5433+
this.$__.version = undefined;
5434+
if (doIncrement) {
5435+
const key = this.$__schema.options.versionKey;
5436+
const version = this.$__getValue(key) || 0;
5437+
this.$__setValue(key, version + 1); // increment version if was successful
5438+
}
5439+
};
5440+
54255441
/*!
54265442
* Module exports.
54275443
*/

lib/model.js

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -523,22 +523,17 @@ Model.prototype.$__save = function(options, callback) {
523523
const versionBump = this.$__.version;
524524
// was this an update that required a version bump?
525525
if (versionBump && !this.$__.inserting) {
526-
const doIncrement = VERSION_INC === (VERSION_INC & this.$__.version);
527-
this.$__.version = undefined;
528-
const key = this.$__schema.options.versionKey;
529-
const version = this.$__getValue(key) || 0;
530526
if (numAffected <= 0) {
527+
const key = this.$__schema.options.versionKey;
528+
const version = this.$__getValue(key) || 0;
531529
// the update failed. pass an error back
532530
this.$__undoReset();
533531
const err = this.$__.$versionError ||
534532
new VersionError(this, version, this.$__.modifiedPaths);
535533
return callback(err, this);
536534
}
537535

538-
// increment version if was successful
539-
if (doIncrement) {
540-
this.$__setValue(key, version + 1);
541-
}
536+
this._applyVersionIncrement();
542537
}
543538
if (result != null && numAffected <= 0) {
544539
this.$__undoReset();
@@ -3666,6 +3661,8 @@ function handleSuccessfulWrite(document) {
36663661
}
36673662

36683663
document.$__reset();
3664+
document._applyVersionIncrement();
3665+
36693666
document.schema.s.hooks.execPost('save', document, [document], {}, (err) => {
36703667
if (err) {
36713668
reject(err);

test/model.test.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7015,6 +7015,53 @@ describe('Model', function() {
70157015
);
70167016
});
70177017

7018+
it('increments version key on successful save (gh-15800)', async function() {
7019+
// Arrange
7020+
const userSchema = new Schema({
7021+
name: [String],
7022+
email: { type: String, minLength: 3 }
7023+
});
7024+
7025+
const User = db.model('User', userSchema);
7026+
const user1 = new User({ name: ['123'], email: '12314' });
7027+
await user1.save();
7028+
7029+
// Act
7030+
const user = await User.findOne({ _id: user1._id });
7031+
assert.ok(user);
7032+
7033+
// Before, __v should be 0
7034+
assert.equal(user.__v, 0);
7035+
7036+
// markModified on array field (triggers $set)
7037+
user.markModified('name');
7038+
await User.bulkSave([user]);
7039+
7040+
const dbUser1 = await User.findById(user._id);
7041+
assert.equal(dbUser1.__v, 1);
7042+
assert.equal(user.__v, 1);
7043+
7044+
// Update another path and markModified
7045+
user.email = '1375';
7046+
await User.bulkSave([user]);
7047+
const dbUser2 = await User.findById(user._id);
7048+
assert.equal(dbUser2.__v, 1);
7049+
assert.equal(user.__v, 1);
7050+
7051+
let reloaded = await User.findById(user._id);
7052+
assert.equal(reloaded.__v, 1);
7053+
7054+
user.email = '1';
7055+
await assert.rejects(
7056+
() => User.bulkSave([user]),
7057+
/email.*is shorter than the minimum allowed length/
7058+
);
7059+
assert.equal(user.__v, 1);
7060+
7061+
reloaded = await User.findById(user._id);
7062+
assert.equal(reloaded.__v, 1);
7063+
});
7064+
70187065
it('saves new documents with ordered: false (gh-15495)', async function() {
70197066
const userSchema = new Schema({
70207067
name: { type: String }

0 commit comments

Comments
 (0)