-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Add session idle timeout and description of "cursor not found" to docs about queries #8720
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
Comments
Having to wait for a few hours to reproduce the issue, that's my favorite kinds of issues 😄 I'll run the script for 1,000 documents, it should take ~3 hours, hopefully that will be enough to reproduce the issue. |
Ran this (1,000 docs = ~3 hours) with no luck in reproducing the issue. const mongoose = require('mongoose');
const { Schema } = mongoose;
mongoose.connect('mongodb://localhost/test', { useCreateIndex: true, useNewUrlParser: true, useUnifiedTopology: true, poolSize: 10 });
const userSchema = new Schema({ counter: { type: Number, default: 0 } });
const User = mongoose.model('User', userSchema);
async function run () {
await User.deleteMany();
const users = Array(1000).fill({});
await User.create(users);
const cursor = User.find({}).cursor();
cursor.addCursorFlag('noCursorTimeout', true);
await cursor.eachAsync(async doc => {
doc.counter++;
await doc.save();
console.log(`Doc ${doc._id} saved, sleeping for 10 seconds...`);
await sleep(10);
});
console.log('Done with documents, closing cursor...');
await cursor.close();
console.log('Closed cursor.');
}
function sleep (seconds) {
return new Promise(resolve => setTimeout(resolve, seconds * 1000));
}
run().catch(console.error);
|
Thank you for helping me with this issue. |
Running the original script would take ~28 hours which isn't an actionable way to demonstrate the issue. Let's leave this open for now, hopefully someone facing the issue will come up with a script that reproduces the issue in a more actionable manner. |
If you increase the sleeping time up to 30 seconds, the error will occur after ~1 hour, which is much shorter. |
Using a delay of 40 seconds causes the script to throw an error after some time. I don't know if
|
So, running this with Currently testing whether this is a mongoose issue or if it happens when running with the native mongodb driver. |
So, running the native driver version of this: const { MongoClient } = require('mongodb');
const delayInSeconds = 40;
const startDate = new Date();
async function run () {
try {
const connection = await MongoClient.connect('mongodb://localhost/gh8720', { useNewUrlParser: true, useUnifiedTopology: true, poolSize: 10, socketTimeoutMS: 50000 });
const User = connection.db('gh8720').collection('users');
await User.deleteMany();
const users = Array.from({ length: 1000 }).map((_, i) => ({ counter: 0, _id: i + 1 }));
await User.insertMany(users);
const cursor = User.find().addCursorFlag('noCursorTimeout', true);
while (await cursor.hasNext()) {
const doc = await cursor.next();
await User.updateOne({ _id: doc._id }, { $set: { counter: doc.counter + 1 } });
console.log(`Saved ${doc._id}, sleeping for ${delayInSeconds} seconds...`);
await sleep(delayInSeconds);
}
console.log('Closing cursor...');
await cursor.close();
console.log('Closed cursor successfully.');
} catch (err) {
console.log(err);
}
console.log(`Started at: ${startDate}, finished at: ${new Date()}`);
}
function sleep (seconds) {
return new Promise(resolve => setTimeout(resolve, seconds * 1000));
}
run().catch(console.error); |
Yep, as I guessed, it's an underlying library issue. Running with the native driver has the same issue, for some reason after exactly 1 hour, 7 minutes, 20 seconds. I created an issue on jira, let's follow up there. |
Thank you for taking in charge 👍 |
Happy to help. Yep, there isn't anything special about the time 1 hour 7 minutes 20 seconds, though. The issue happens because of this (includes a possible fix). TL;DR: Note that a cursor works in batches, so if your first batch (101 documents) in this case take more than 30 minutes, when the cursor tries to fetch the new the session has already expired, and Mongo will throw an error. The fix is to explicitly start a session, and refresh it before it expires, for more on that, check out the link provided. |
Ok so I guessed right in the first place.
|
Yep, your guess was correct! If I were you, I would refresh the session every 29 minutes, reducing the default batch size doesn't seem optimal because it might impact performance negatively. Do you need any further assistance with this issue? |
Yes I don't know why neither, but if the issue comes from MongoDB, it probably downgrades the MongoDB version used as well. Wouldn't it be nice to mention the Session Idle Timeout in the Mongoose documentation ? This way people would be aware that this issue could happen. |
I don't think mongoose nor the driver can control the version of the database they're connected to, weird behavior indeed. I don't know if the right place to put this is mongoose documentation, this is a purely MongoDB's issue. Curious to know what @vkarpov15 thinks about this. |
It's not possible that the issue appears after the upgrade of the driver ? |
Actually, after re-reading the MongoDB docs, it specifies that this behavior is implemented in the drivers and the shell.
So, yes. That's probably the case. |
Might be worth mentioning https://docs.mongodb.com/manual/reference/method/cursor.noCursorTimeout/#session-idle-timeout-overrides-nocursortimeout in the query docs. Admittedly keeping a cursor idle for 30 minutes is not a common use case, but something to make sure people are aware of. |
Do you want to request a feature or report a bug?
Report a bug
What is the current behavior?
I recently bumped my Mongoose version from 5.5.7 to 5.9.6 and I spotted a issue with cursors.
The error is
MongoError: cursor id XXX not found
(even withcursor.addCursorFlag('noCursorTimeout', true)
.If the current behavior is a bug, please provide the steps to reproduce.
You can reproduce the bug by running this script (for a few hours) :
What is the expected behavior?
The error must not occur.
What are the versions of Node.js, Mongoose and MongoDB you are using?
Node v12.16.1
Mongoose v5.9.6
MongoDB v4.0.16
I think the error has to do with the MongoDB idle session timeout (https://docs.mongodb.com/manual/reference/method/cursor.noCursorTimeout/) but I am no expert.
The text was updated successfully, but these errors were encountered: