I am using mongoose to connect to my Mongodb Atlas cluster through my nodejs server.
There is a certain operation which is done as a transaction. Mongoose needs mongoose.startSession()
to be called to start a transaction. Very infrequently, this mongoose.startSession()
call hangs indefinitely. There is no certain way to reproduce this.
log.info('starting lock session');
const mongoSession = await mongoose.startSession();
log.info('lock session started');
In above code, starting lock session.
gets logged, but lock session started
doesn't get logged when issue occurs.
I connect to the db like below:
const dburl = 'mongodb+srv://myuser:[email protected]/mydb?retryWrites=true&w=majority';
mongoose.connect(dburl, {useNewUrlParser: true}, err => {
if (err) {
log.warn('Error occurred when connecting to database. ' + err);
}
});
What could be the reason for this? Could this be due to something wrong with the database? Is there any way I can further troubleshoot this?
This looks like a bug in mongoose, and I reported it to mongoose but still didn't get a response.
https://github.com/Automattic/mongoose/issues/8325
I wrote following function which I can use to wait until the mongoose connection is ready before calling startSession()
, and it fixes my problem.
function waitForMongooseConnection(mongoose) {
return new Promise((resolve) => {
const connection = mongoose.connection;
if (connection.readyState === 1) {
resolve();
return;
}
console.log('Mongoose connection is not ready. Waiting for open or reconnect event.');
let resolved = false;
const setResolved = () => {
console.log('Mongoose connection became ready. promise already resolved: ' + resolved);
if (!resolved) {
console.log('Resolving waitForMongooseConnection');
resolved = true;
resolve();
}
};
connection.once('open', setResolved);
connection.once('reconnect', setResolved);
});
}
With above function, I can start session like below:
log.info('starting session');
await waitForMongooseConnection(mongoose);
const mongoSession = await mongoose.startSession();
log.info('session started');
Note that I had to turn off useUnifiedTopology
. Otherwise, 'reconnect' didn't get called.
mongoose.connect(config.db, {useNewUrlParser: true, useUnifiedTopology: false}, err => {
if (err) {
log.warn('Error occurred when connecting to database. ' + err);
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With