Hello I noticed some strange behaviour in node.js with felix geisendörfers awesome mysql module.
I have the following structure in my express app.
The routes use the Router function of express. Every routing file (A-C) has to access the mysql server. But I was to lazy to write a connection and the connection options in every routing script file. So I made another file called DBServer.js It is as follows (inspired by some hints from someone here in stackoverflow):
var mysql = require('mysql');
exports.connect = function (){
var db_config = {
host: '127.0.0.1',
user: 'my username',
password: '********',
database: 'my database'
};
var connection;
function autoConnect() {
connection = mysql.createConnection(db_config);
connection.connect(function(err) {
if(err) {
console.log('DBServer Error: cannot connect to db. Reconnect attempt in 2 seconds...\nError: ', err);
setTimeout(autoConnect, 2000);
}
else{
console.log('DBServer connected successfully...');
}
});
connection.on('error', function(err) {
if(err.code === 'PROTOCOL_CONNECTION_LOST') {
console.log('DBServer Error: lost connection. Reconnect attempt in 2 seconds...\nError: ', err);
autoConnect();
}
else {
console.log('DBServer Error: minor error\nError: ', err);
}
});
}
autoConnect();
return connection
}
In every routing file I require this DBServer file via:
var db = require('./lib/DBServer').connect();
When I start my app, the console logs 3 times
DBServer connected successfully...
DBServer connected successfully...
DBServer connected successfully...
... as intended.
Everything works perfect. I run the App with forever and every time the script losses connection to the db-server (what happens from time to time) it reconnects again... as intended.
... BUT! Except of one script. Script routesA.js stops working when it comes to a mysql query. The script freezes but does not quit. I have to stop and restart it again. There is no difference between the invocation of DBServer.js between routesA, routesB or routesC. And it works pretty good... But it seems that if routesA looses connection it does not reconnect again... routesB and routesC still works fine.
So I changed the way how script routesA.js connects to the database. I connect now in script routesA.js not via the DBServer.js and require but the manual way
var mysql = require('mysql');
var db = mysql.createConnection({
host: '127.0.0.1',
user: 'my username',
password: '******',
database: 'ma database'
});
db.connect();
Now it works... and runs for days without problems. But the reason why this works is, because now I don't have an error handling in script routesA.js.. so forever detects a script exit and restarts... and everything works again. But I don't want that way. I want a proper error handling like in DBServer.js. As said this works for script B and C, but not script A...
I know that it is strange and difficult to say, what might be the problem. But maybe someone has had some similar problem.
Another question here is: How do you handle the database connections with multiple script files. I there a way to share one mysql connection for all script files you have in an app?
kind regards martin
The reason probably has to do with the fact that you're returning the initial connection object on require(), but if you get disconnected, you reassign the connection variable which the external scripts do not have a reference to (they still only have a reference to the old/original connection object).
I should also note that if you're using the mysql2 module (compatible with mysql except much faster), there is a connection.ping() method that you can use to periodically ping the server to help keep the connection alive.