Reputation: 381
My code is too long to post in here, but basically I use socket.io server to pull data from database and refresh in the client every 1 second. Like this:
function updateTimer(){
//db->query
io.sockets.emit('updated data', data);
}
setInterval(updateTimer, 1000);
After a certain amount of time, the server just stops emitting data. I use a chat on the website as well and it stops too. But in the server console nothing is shown, no errors or any outputs, just "listening on port 3000..." stays on the screen all the time.
I thought it could be the loop maybe but I think there's no other way of refreshing data every 1 second, am I right? If someone can help me and needs the full code please open a discussion and I'll paste it somewhere.
EDIT for the function code:
function checkRoulleteTime() {
try {
pool.getConnection(function(err, connection) {
connection.query('SELECT * FROM `roullete` WHERE status=\'active\'', function(err, rows) {
if (err) {
console.log(err);
return;
}
if (rows.length == 0) return;
var time = rows[0].time - (Math.floor(Date.now() / 1000));
if (time <= 1) {
connection.query('UPDATE `roullete` SET `status`=\'closed\' WHERE `id`=\'' + rows[0].id + '\'', function(error, fields) {
if (error) throw error;
});
setTimeout(roll, 1000);
setTimeout(function(){
io.sockets.emit('add hist');
}, 10500);
setTimeout(updatePoints, 12000);
setTimeout(newRound, 12500);
}
var contagem = Object.keys(clients).length;
io.sockets.emit('login count', contagem);
io.sockets.emit('roullete time', time);
connection.query('SELECT SUM(points) as points FROM `roullete_bets` WHERE `round`=\'' + rows[0].id + '\' AND `color`=\'black\'',function(error2, rows2){
if (error2) throw error2;
connection.query('SELECT SUM(points) as points FROM `roullete_bets` WHERE `round`=\'' + rows[0].id + '\' AND `color`=\'green\'',function(error4, rows4){
if (error4) throw error4;
connection.query('SELECT SUM(points) as points FROM `roullete_bets` WHERE `round`=\'' + rows[0].id + '\' AND `color`=\'red\'',function(error3, rows3){
if (error3) throw error3;
var onBlack = rows2[0].points;
var onRed = rows3[0].points;
var onGreen = rows4[0].points;
io.sockets.emit('calculations', {"time": time, "black" : onBlack, "red" : onRed, "green" : onGreen});
});
});
});
});
connection.release();
});
} catch(e) {
console.log('error here:'+e);
}
setTimeout(checkRoulleteTime, 1000);
}
setTimeout(checkRoulleteTime, 1000);
Alright, that's my code.
Upvotes: 0
Views: 3150
Reputation: 707148
My guess is that you have some sort of programming error in your database query that, after a little while exhausts some resources so your database query starts failing every time, throwing an exception or just returning an error and thus you don't ever send any data because of the error. Because the code is inside the setInterval()
callback, any exception is not logged for you.
We could probably help you further if you included your actual database code, but you can start to debug it yourself by putting an exception handler around it like this:
function updateTimer(){
try {
//db->query
io.sockets.emit('updated data', data);
} catch(e) {
console.log(e);
}
}
setInterval(updateTimer, 1000);
And, if your DB query is async (which I'm assuming it is), you will need to have explicit error handling and an exception at each callback level (since exceptions don't propagate up async callbacks).
If your database may get slow, then it might be safer to change your recurring code to work like this:
function updateTimer(){
try {
//db->query
io.sockets.emit('updated data', data);
} catch(e) {
console.log(e);
}
// schedule next updateTimer() call when this one has finished
setTimeout(updateTimer, 1000);
}
// schedule first updateTimer() call
setTimeout(updateTimer, 1000);
You have LOTS of places in your code where you are leaking a pooled connection and lots of places where you are not logging an error. My guess is that you are running out of pooled connections, getting an error over and over that you don't log.
Here's a version of your code that attempts to clean things up so all errors are logged and no pooled connections are leaked. Personally, I would write this code using promises which makes robust error handling and reporting a ton easier. But, here's a modified version of your code:
function checkRoulleteTime() {
try {
pool.getConnection(function (err, connection) {
if (err) {
console.log("Failed on pool.getConnection()", err);
return;
}
connection.query('SELECT * FROM `roullete` WHERE status=\'active\'', function (err, rows) {
if (err) {
connection.release();
console.log(err);
return;
}
if (rows.length == 0) {
connection.release();
return;
}
var time = rows[0].time - (Math.floor(Date.now() / 1000));
if (time <= 1) {
connection.query('UPDATE `roullete` SET `status`=\'closed\' WHERE `id`=\'' + rows[0].id + '\'', function (error, fields) {
if (error) {
console.log(error);
connection.release();
return;
}
});
setTimeout(roll, 1000);
setTimeout(function () {
io.sockets.emit('add hist');
}, 10500);
setTimeout(updatePoints, 12000);
setTimeout(newRound, 12500);
}
var contagem = Object.keys(clients).length;
io.sockets.emit('login count', contagem);
io.sockets.emit('roullete time', time);
connection.query('SELECT SUM(points) as points FROM `roullete_bets` WHERE `round`=\'' + rows[0].id + '\' AND `color`=\'black\'', function (error2, rows2) {
if (error2) {
console.log(error2);
connection.release();
return;
}
connection.query('SELECT SUM(points) as points FROM `roullete_bets` WHERE `round`=\'' + rows[0].id + '\' AND `color`=\'green\', function (error4, rows4) {
if (error4) {
console.log(error4);
connection.release();
return;
}
connection.query('SELECT SUM(points) as points FROM `roullete_bets` WHERE `round`=\'' + rows[0].id + '\' AND `color`=\'red\'', function (error3, rows3) {
connection.release();
if (error3) {
console.log(error3);
return;
}
var onBlack = rows2[0].points;
var onRed = rows3[0].points;
var onGreen = rows4[0].points;
io.sockets.emit('calculations', {
"time": time,
"black": onBlack,
"red": onRed,
"green": onGreen
});
});
});
});
});
});
} catch (e) {
console.log('error here:' + e);
}
setTimeout(checkRoulleteTime, 1000);
}
setTimeout(checkRoulleteTime, 1000);
And to give you an idea how much simpler it can be to do error handling and chaining of sequential or dependent async functions, here's your function rewritten using promises. I have no idea if this runs without error since I have no way of testing it, but it should give you an idea how much cleaner programming with promises can be:
var Promise = require('bluebird');
pool = Promise.promisifyAll(pool);
function logErr(err) {
console.log(err);
}
function checkRoulleteTime() {
pool.getConnectionAsync().then(function(connection) {
var query = Promise.promisify(connection.query, {context: connection});
return query('SELECT * FROM `roullete` WHERE status=\'active\'').then(function(rows) {
if (rows.length !== 0) {
var time = rows[0].time - (Math.floor(Date.now() / 1000));
if (time <= 1) {
query('UPDATE `roullete` SET `status`=\'closed\' WHERE `id`=\'' + rows[0].id + '\'').catch(logErr);
setTimeout(roll, 1000);
setTimeout(function () {
io.sockets.emit('add hist');
}, 10500);
setTimeout(updatePoints, 12000);
setTimeout(newRound, 12500);
}
var contagem = Object.keys(clients).length;
io.sockets.emit('login count', contagem);
io.sockets.emit('roullete time', time);
function doQuery(color) {
return query('SELECT SUM(points) as points FROM `roullete_bets` WHERE `round`=\'' + rows[0].id + '\' AND `color`=\'' + color + '\'');
}
return Promise.all([doQuery('black'), doQuery('green'), doQuery('red')]).then(function(results) {
io.sockets.emit('calculations', {
"time": time,
"black": results[0][0].points,
"green": results[1][0].points,
"red": results[2][0].points
});
});
}
}).catch(logErr).finally(function() {
connection.release();
setTimeout(checkRoulleteTime, 1000);
});
}, function(err) {
console.log("Err getting connection: ", err);
});
}
Upvotes: 1