Good way of handling MongoError: server instance pool was destroyed - node.js

I'm running a daemon with a mongo connection pool. It runs fine for days but eventually it crashes and every subsequent request gets this error:
MongoError: server instance pool was destroyed
The code is similar to this:
var MongoClient = require('mongodb').MongoClient;
var express = require('express');
var app = express();
MongoClient.connect(config.mongo.url, function(err, db) {
app.use('/', function(req, res, next) {
db.collection('somecollection').find({}).toArray(function(err, result) {
console.log(result);
});
})
var server = require('http').Server(app);
server.listen(config.worker.port, function() {
var address = server.address();
logger.info({
address: address.address,
port: address.port
}, 'New Worker created');
});
});
Restarting the process fixes the issue, but I would like the application to somehow elegantly reconnect and reset the "db" object there.

This is what we are using - if connection fails, it tries to reconnect after 5 seconds. It is written for mongoose, but we are just re-running connection when detecting error, which should be done for any framework.
// Connect to mongodb
const connect = function () {
const options = {server: {socketOptions: {keepAlive: 1}}};
mongoose.connect(config.db, options);
};
connect();
mongoose.connection.on('error', err => {
let stack;
if (err) {
stack = err.stack;
}
winston.error('Mongo crashed with error', {err, stack});
}); // eslint-disable-line no-console
mongoose.connection.on('disconnected', () => {
setTimeout(connect, 5000);
});

Related

Prevent closing connection on bad request

I have an express server.
I set socket.setKeepAlive(true, 60000); in order to maintain persistent connection for at least 1min.
Here is the code:
var express = require("express");
var app = express();
var server = app.listen(8080);
app.get("/", (req, res) => {
res.write("Hello Riko");
});
// server.listen(3000);
server.on("connection", function(socket) {
console.log("A new connection was made by a client.");
socket.setKeepAlive(true, 60000);
socket.on("data", data => {
console.log(data);
});
// 30 second timeout. Change this as you see fit.
});
When the client send invalid request, it receives 400 Bad Request
How to prevent connection close on invalid request?
Yes the suggestion i made in the comments works.
server.on('clientError',cb) prevents the default behavior of the stack.
I encountered one problem though. It registers event listener for error event every time clientError is fired. Therefore I changed the code litle bit and ended up with a solution that works for me:
var express = require("express");
var app = express();
var server = app.listen(8080);
app.get("/", (req, res) => {
res.send("Hello Riko");
});
onSocketError = err => {
console.log("Socket Error: " + err);
};
server.on("connection", function(socket) {
socket.on("data", data => {
console.log(data.toString());
});
console.log("A new connection was made by a client.");
});
server.on("clientError", (err, socket) => {
socket.removeAllListeners("error");
});
Hope this would help someone with similar problem.

Unable to connect with redis in app.get method

I am trying to learn use case of redis. As each tutorial is suggesting that it is better for caching a data.
I have made a simple demo where I am trying to connect with redis server in a web service get method.
var redis = require('redis');
var client = redis.createClient();
var express = require('express')
var app = express()
var port = process.env.PORT || 8080; // <== this is must
app.get('/fetch_offers', function (req, res) {
client.on('connect', function() {
console.log('connected');
});
});
app.listen(port, function () {
console.log(port)
})
I am trying to access it on localhost machine like http://localhost:8080/fetch_offers
I debugged it using console.log method but it does not print connected message. When I make this method outside the app.get... then it prints on executing node app.js.
I want it should make a redis connection on hitting a URL. I am not sure what is best way ? Can anyone help me ?
var redis = require('redis');
var client = redis.createClient();
var express = require('express')
var app = express()
var port = process.env.PORT || 8080; // <== this is must
client.on('connect', function() {
console.log('connected');
});
app.get('/fetch_offers', function (req, res) {
});
app.listen(port, function () {
console.log(port)
})
What wrong I am doing here ?
It doesn't print connection message because the event fires well before you hit the endpoint - at which point nothing is listening for it and it gets lost. Try something like this:
var redis = require('redis');
var client = redis.createClient();
client.on('connect', () => {
console.log('Redis connected');
});
client.on('ready', () => {
console.log('Redis ready');
});
client.on('error', (err) => {
console.log('Redis error:', err.message);
});
and then in your route handler you can use ping to see if you're connected:
app.get('/fetch_offers', function (req, res) {
client.ping((err, data) => {
if (err) {
console.log('Ping error:', err);
return;
}
console.log('Ping response:', data);
});
});
It would be slightly easier if you use promise-redis and async/await:
app.get('/fetch_offers', async (req, res) => {
try {
console.log('Ping response:', await client.ping());
} catch (err) {
console.log('Ping error:', err);
}
});

Error: Global connection already exists. Call sql.close() first

Hi I am creating node js restful api by using sqlserver database , i prepare get api when i am using that api output is shown in json format, while refreshing that browser gain its shows "Error: Global connection already exists. Call sql.close() first."error . I am adding code
var express = require("express");
var sql = require("mssql");
var app = express();
//Initiallising connection string
var dbConfig = {
user: 'sa',
password: 'India123',
server: 'localhost',
database: 'sample'
};
app.get('/login', function (req, res) {
// connect to your database
var data = {
"user": ""
};
sql.connect(dbConfig, function (err) {
if (err) console.log(err);
var request = new sql.Request();
request.query('select * from Login', function (err, result) {
if (err) console.log(err)
// send data as a response
//res.send(result.recordset);
data["user"] = result.recordset;
res.send(data);
});
});
});
var server = app.listen(5000, function () {
console.log('Server is running..');
});
Please correct me code . thanks advance
// db.js
var mssql = require("mssql");
var dbConfig = {
user: 'sa',
password: 'India123',
server: 'localhost',
database: 'sample'
};
var connection = mssql.connect(dbConfig, function (err) {
if (err)
throw err;
});
module.exports = connection;
// app.js
var db = require("db");
var express = require("express");
var app = express();
app.get('/login', function (req, res, next) {
var request = new db.Request();
request.query('select * from Login', function (err, result) {
if (err)
return next(err);
var data = {};
data["user"] = result.recordset;
res.send(data);
});
});
var server = app.listen(5000, function () {
console.log('Server is running..');
});
Don't use sql.Connection() any more, instead use sql.ConnectionPool()
Connections
Internally, each ConnectionPool instance is a separate pool of TDS connections. Once you create a new Request/Transaction/Prepared Statement, a new TDS connection is acquired from the pool and reserved for desired action. Once the action is complete, connection is released back to the pool. Connection health check is built-in so once the dead connection is discovered, it is immediately replaced with a new one.
IMPORTANT: Always attach an error listener to created connection. Whenever something goes wrong with the connection it will emit an error and if there is no listener it will crash your application with an uncaught error.
Create pool and use connection.
const pool = new sql.ConnectionPool({ /* config */ })
Entire Article how to use pool and close pool.
https://www.npmjs.com/package/mssql
var sql = require("mssql");
const pool = new sql.ConnectionPool({
user: 'sa',
password: 'Pass#123',
server: 'SAI-PC',
database: 'Demo'
})
var conn = pool;
conn.connect().then(function () {
var req = new sql.Request(conn);
req.query("SELECT * FROM Product").then(function (recordset) {
console.log(recordset);
conn.close();
})
.catch(function (err) {
console.log(err);
conn.close();
});
})
.catch(function (err) {
console.log(err);
});

MongoError: socket hang up

I am trying to connect to the mongodb database on mongolabs(mlabs). I connect successfully when I run the code on my local computer and server.But When I run on my aws server I get this error database error { [MongoError: socket hang up] name: 'MongoError', message: 'socket hang up' }
Code trial.js:
var express = require('express');
var app = express();
var mongoose = require('mongoose');
var mongojs = require('mongojs');
var db = mongojs('mongodb://user:pass#ds01312192.mlab.com:133492/database', ['mohd'], { ssl : true });
db.on('error', function (err) {
console.log('database error', err);
});
db.on('connect', function () {
console.log('database connected');
});
db.mohd.find({}, function (err, docs) {
if(err){
console.log("error");
}else{
console.log(docs+"found");
}
});
app.set('view engine','ejs');
app.get('/',function(req,res){
console.log("hi");
});
app.listen(9000,function(){
console.log("server strated");
});
// catch 404 and forward to error handler
module.exports = app;
Got connection error on Amazon Web Service server but successful on local computer.
Ok so I solved the issue it was due to ssl connect method just removed it and was solved.
Use Instead:
var db = mongojs('mongodb://user:pass#ds01312192.mlab.com:133492/database', ['mohd']);

node, socket.io - authorization fail

This is a skeleton of my app.js file.
What I don't understand is way it doesn't read and print "log authorisation".
I followed this https://github.com/LearnBoost/socket.io/wiki/Authorizing
var express = require('express');
mongoose = require('mongoose');
var MongoStore = require('connect-mongo')(express);
app = express();
// costants
var SITE_SECRET = 'xxx';
// mongoose
mongoose.connect('mongodb://127.0.0.1/test');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function callback () {
console.log('Mongoose connection is now opened');
});
// pass same objects from Express to Socket.IO so they match
var parseCookie = express.cookieParser(SITE_SECRET);
var store = new MongoStore({
mongoose_connection: mongoose.connection,
db: mongoose.connections[0].db
});
app.configure(function(){
app.set('host', '127.0.0.1');
app.set('port', 1111);
// init cookie-session
app.use(parseCookie);
app.use(express.session({
secret : SITE_SECRET
,store : store
,cookie: { maxAge: new Date(Date.now() + (1000*60*60*24*30*12)) }
}));
});
// create and start server
var server = require('http').createServer(app)
server.listen(app.get('port'));
// socket.io
var io = require('socket.io').listen(8080);
io.configure(function() {
console.log('log configure <-- it read this. ok!');
io.set('authorization', function(handshake, callback) {
console.log("log authorisation <-- but it doesn't read this. why??");
if (handshake.headers.cookie) {
parseCookie(handshake, null, function() {
handshake.sessionID = handshake.signedCookies['connect.sid'];
store.get(handshake.sessionID, function(err, session) {
callback(null, true);
});
});
} else {
// they client has no session yet, don't let them connect
callback('No session.', false);
}
});
});
clients = {};
io.sockets.on('connection', function (socket) {
// save to a global object
console.log('save session');
var session = socket.handshake.sessionID;
clients[session] = socket;
socket.on('disconnect', function() {
console.log('remove session');
delete clients[session];
});
});
// routes
app.get('/on', function(req, res){
var socket = clients[req.sessionID];
socket.on('test', function (data) {
console.log(data);
});
});
app.get('/emit', function(req, res){
var socket = clients[req.sessionID];
socket.emit('test', "ciao");
console.log("emit");
});
when I start the server on the terminal I see this:
starting `node app.js`
Mongoose connection is now opened
info - socket.io started
log configure
And if I load the page "/on"
the error is:
TypeError: Cannot call method 'on' of undefined
I'm stack here from too much... What's wrong in this?
Maybe someone had the same problem...
try making socket.io listen to server port, you define 1111 as a port for server and 8080 for socket.io , you application is available for access at localhost:1111.
short example
var server = http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
io.listen(server);

Resources