I am developing an express application which connects to a MongoDB database. It is possible that my express server looses the connection to database, but how should my express server react to this scenario? I prepared the following code where i check for a lost connection and then I kill the app.
const registerCustomer = async (req, res) => {
let validRegistrationCode;
try {
validRegistrationCode = await CustomerRegistrationCode.findOne({ code: req.body.code });
} catch (error) {
if (error instanceof MongoNetworkError || error instanceof MongooseServerSelectionError) {
console.error('Mongo | Mongoose Network Error occurred');
}
process.exit(1);
}
return res.json({ obj: validRegistrationCode });
}
For every access to the DB, I have to check for a connection error and I think this makes the code ugly. How can this be improved?
I think the failure of connection to mongoDB usually doesn't happen or it can also happen in case of network is loss, or your path, syntax is not correct and what you should do is check only once when setup mongoose to connect to your database, every time you save code nodemon will help you check if you have successfully connected
// connect model with database
const mongoose = require('mongoose');
async function connect() {
try {
await mongoose.connect('mongodb://localhost:27017/collections_clothes', {
// useNewUrlParser: true,
// useUnifiedTopology: true,
// useCreateIndex: true,
});
console.log("Access Database Success!");
} catch (error) {
console.log("Access FAIL!");
}
}
module.exports = { connect };
Related
I have seen this issue published in a few places however I still don't have a solution.
I am using a node server and can connect to my database correctly with a status of 1 for connected.
However when I send requests to the mongodb database, the request pends and times out.
I have tried adding my IP to mongodb, putting my connection in an async function. and also removing mongoose and re installing it.
My structure is like this
app
client
node_modules > mongoose 5.13.14
server
node_modules > mongoose 5.13.14
My connection to mongodb is like this.
mongoose.connect(process.env.MONGOOSE_CONNECTION, { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true })
.then(res =>{
console.log("Connected to Database")
}).catch(function (reason) {
console.log('Unable to connect to the mongodb instance. Error: ', reason);
});
An example of an endpoint that fails is here.
router.get('/therapists', (req, res) => {
signUpTemplate.find({}, (err, result) => {
if (err) {
console.log(err)
} else {
res.status(200).send({
results: result
})
}
})
})
which results in error
MongooseError: Operation therapists.find() buffering timed out after 10000ms
Can someone help me please as I am really not sure what the solution is.
Thank you!
MongoClient.connect(this._config.connectionString, {
useNewUrlParser: true,
useUnifiedTopology: true,
}, (err, db) => {
if (err) {
console.log(`error on connect : ${err}`);
return console.dir(err);
}
console.log('We are connected');
this._client = db;
});
This piece helps me connect to mongodb running locally, and works fine when DBserver is up and running. But if i stop db server and then try to execute this...it doesnt call the call back. Is there a way i can get call back in case of DB is down or not reachable?
below code doesnt get call back, in case of future DB errors.
this._client.on('error', args => this.onError(args));
Because of this issue of not getting call backs, in case of any severe errors...my server goes down without showing any error.
I'm fairly new to mongoose and node. I am trying to write a simple API using Nodejs and Express, wherein I send a MongoDB URI, and if it is valid, i.e. the username/password combo works and a connection to that URI is successfully established, a success message should be returned.
I initially tried to create a separate function to try to connect to the given URI:
function testURI(uri) {
mongoose.connect(uri, {useNewUrlParser: true} );
mongoose.connection.on("connected", function() { return true } );
}
module.exports.test = function(req, res) {
var uri = req.body.uri;
if(testURI(uri)) res.status(200).json({'success': true});
else res.status(400).json({'success': false});
};
But this failed, since mongoose connects asyncronously, and the "connected" event callback is not able to return true for the main function
So I dropped the idea for a separate function, and instead tried to achieve it within the module.exports.test function:
module.exports.test = function(req, res) {
var uri = req.body.uri;
mongoose.connect(uri, { useNewUrlParser: true, connectTimeoutMS: 2500 });
mongoose.connection.on("connected", function() {
mongoose.connection.close();
res.status(200).json({'success': true});
});
mongoose.connection.on("error", function(err) {
result = {
'error': true,
'errorMsg': 'Error: Could not connect to the given host.'
}
mongoose.connection.close();
res.status(400).json(result);
});
};
This works fine, except that the server dies after responding to one request. Once I try with an invalid URI, it returns HTTP 400 as expected, but then when I send another request with a different URI, the app just crashes with the error
Error: Can't set headers after they are sent.
And then I have to restart the app before I can send another request. Apparently the two separate res.status(200).json and res.status(400).json in the same controller are creating the problem and the app is treating subsequent requests also as the same request.
Fixed the problem by creating a custom middleware. Instead of returning the result via res.status().json() within the controller function, I used this function as a middleware and returned the result from the next function
module.exports.test = function(req, res, next) {
var uri = req.body.uri;
mongoose.connect(uri, { useNewUrlParser: true, connectTimeoutMS: 2500 });
mongoose.connection.on("connected", function() {
mongoose.connection.close();
req.status = 200;
req.result = {'success': true};
next();
});
mongoose.connection.on("error", function(err) {
result = {
'error': true,
'errorMsg': 'Error: Could not connect to the given host.'
}
mongoose.connection.close();
req.status = 400;
req.result = result;
next();
});
};
module.exports.returnDb = function(req, res) {
res.status(req.status).json(req.result);
};
Edited route declaration:
router.route('/test')
.post(client.test, client.returnDb);
I'd like my Node JS app to exit immediately if it can't connect to Mongo. I'm using the mongodb node library.
I've reduced the code down to
const {MongoClient} = require('mongodb');
MongoClient.connect('mongodb://localhost:27017');
If Mongo is not running, I get an UnhandledPromiseRejectionWarning with ECONNREFUSED, which I fully expect, but then the program hangs and never exits. This is with Node version 10.0.0.
Since the connection never succeeded I don't have a connection handle to close. I've tried various ways to catch the rejected promise, but I have been unsuccessful in getting the program to exit.
What do I need to do to shut down the MongoClient and make the program exit in this case?
Your application is remaining alive because it is trying to reconnect. You can try disabling the recconect:
MongoClient.connect('mongodb://localhost:27017', {
autoReconnect: false
}, (err, client) => {
if (client) client.close();
});
Or, you can terminate the process using process.exit(1) to kill the program.
const {
MongoClient
} = require('mongodb');
// Callback syntax
MongoClient.connect('mongodb://localhost:27017', (err, db) => {
if (err) process.exit(1);
});
// Promise syntax
MongoClient
.connect('mongodb://localhost:27017')
.catch(err => {
process.exit(1);
});
// Async/await syntax
(async function() {
let db;
try {
db = await MongoClient.connect('mongodb://localhost:27017');
} catch (err) {
process.exit(1);
}
}());
I'm trying to connect to my cluster on mongoDB Atlas via Mongoose.connect(), but every time i try to connect i get an exception "MongoError: authentication fail"
I know MongoDB Atlas is new mongo as a service could it be not supported by mongoose yet?.
The answer in this related post is correct. You should:
not mix options with connection string (if done so)
make sure your IP you are running on is whitelisted and your network allows connections to Atlas
make sure the user has sufficient permissions
use the connection string as is provided by atlas and just provide it to
mongoose.connect(uri);
MongoError: authentication fails - It means your name or password or dbname is not correct -
uri sample -
const uri =
"mongodb+srv://<username>:<password>#firstcluster.4rc4s.mongodb.net/<dbname>?retryWrites=true&w=majority";
Suppose username is - najim & password is 1234 & dbname is pets (Note - default dbname is test but you can write whatever you want) then my uri will be with above credentails -
const mongoAtlasUri =
"mongodb+srv://najim:1234#firstcluster.4rc4s.mongodb.net/pets?retryWrites=true&w=majority";
to connect with moongoose
try {
// Connect to the MongoDB cluster
mongoose.connect(
mongoAtlasUri,
{ useNewUrlParser: true, useUnifiedTopology: true },
() => console.log(" Mongoose is connected")
);
} catch (e) {
console.log("could not connect");
}
const mongoAtlasUri =
"mongodb+srv://<username>:<password>#firstcluster.4rc4s.mongodb.net/<dbname>?retryWrites=true&w=majority";
try {
// Connect to the MongoDB cluster
mongoose.connect(
mongoAtlasUri,
{ useNewUrlParser: true, useUnifiedTopology: true },
() => console.log(" Mongoose is connected"),
);
} catch (e) {
console.log("could not connect");
}
const dbConnection = mongoose.connection;
dbConnection.on("error", (err) => console.log(`Connection error ${err}`));
dbConnection.once("open", () => console.log("Connected to DB!"));
try {
mongoose.connect( uri, {useNewUrlParser: true, useUnifiedTopology: true}, () =>
console.log("connected"));
}catch (error) {
console.log("could not connect");
}
this works fine , try it
"mongodb+srv://:#cluster0.vvkuk.mongodb.net/"
also in the atlas, in security go to network access, there will be small buttons edit and delete click on edit, and in the edit, there will to two options the first option is ADD CURRENT IP ADRESS & the second option will be ALLOW ACCESS FROM ANYWHERE
go for the first option & then click confirm