-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DocumentNotFoundError instead of VersionError during save #11295
Comments
Although this has been fixed, I want to explain the cause of this bug and another possible fix, in case someone else is interested at this. The cause of this bug is the line of code below. It assigns the same other.name = 'WallE'; If you assign a different value to other.name = 'Steve'; // get VersionError as expected But why? https://github.com/Automattic/mongoose/blob/master/lib/model.js#L314 Model.prototype.$__handleSave = function(options, callback) {
// ...
const delta = this.$__delta();
if (delta) {
// model has some changes, this case works well
} else {
// model has no changes, may fix this bug in this else block
} Mongoose use [
{ _id: new ObjectId("..."), __v: 0 },
{ '$set': { name: 'Steve' }, '$inc': { __v: 1 } }
] Since Mongoose has handled this case well, let's see how it handles the } else {
const optionsWithCustomValues = Object.assign({}, options, saveOptions);
const where = this.$__where();
if (this.$__schema.options.optimisticConcurrency) {
const key = this.$__schema.options.versionKey;
const val = this.$__getValue(key);
if (val != null) {
where[key] = val;
}
}
// where = { _id: new ObjectId("..."), __v: 0 }
this.constructor.exists(where, optionsWithCustomValues).
then((documentExists) => {
// Check whether document has beed changed before updating
if (!documentExists) {
// document has been changed, in this case, __v is 1 in the database
const matchedCount = 0;
return callback(null, { $where: where, matchedCount });
}
const matchedCount = 1;
callback(null, { $where: where, matchedCount });
}).
catch(callback);
return;
} Later in Model.prototype.$__save = function(options, callback) {
// ...
if (this.$__.version && !this.$__.inserting) { // This is the line of code before the fix
// this.$__.version is undefined so it goes to the next if block
// We want it go into this if block after the fix
// ...
if (numAffected <= 0) {
// the update failed. pass an error back
this.$__undoReset();
const err = this.$__.$versionError ||
new VersionError(this, version, this.$__.modifiedPaths);
return callback(err);
}
// ...
}
if (result != null && numAffected <= 0) {
// result = { $where: where, matchedCount } in the code block above
// and hence DocumentNotFoundError instead of VersionError
error = new DocumentNotFoundError(result.$where,
this.constructor.modelName, numAffected, result);
// ...
}
} Below is my fix of this bug, and it passes all the latest related tests, so I consider it a possible fix. } else {
const optimisticConcurrency = this.$__schema.options.optimisticConcurrency
const optionsWithCustomValues = Object.assign({}, options, saveOptions);
const where = this.$__where();
if (optimisticConcurrency) {
// ...
}
this.constructor.exists(where, optionsWithCustomValues).
then((documentExists) => {
if (!documentExists) {
if (optimisticConcurrency) { // the fix here
this.$__.version = VERSION_INC;
}
const matchedCount = 0;
return callback(null, { $where: where, matchedCount });
}
// ...
}).
catch(callback);
return;
} Basically it sets |
Do you want to request a feature or report a bug?
Bug
What is the current behavior?
This is the same issue as described in #10974
If the current behavior is a bug, please provide the steps to reproduce.
Using the same script created by @IslandRhythms in #10974 (comment)
I am getting a DocumentNotFound:
What is the expected behavior?
A VersionError should be thrown, not a DocumentNotFound error.
What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.
Mongoose: 6.1.8
Node: v16.6.1
The text was updated successfully, but these errors were encountered: