I am doing a project where I have to continuesly poll the status of a number of devices on the network (local network) and then emit the status of this to the clients on a socket.io connection.
I can get the code up and running when the connectio to the devices are good, but if one of them falls off the network I get:
RangeError: Maximum call stack size exceeded
at Function.isBuffer (buffer.js:398:36)
at hasBinary (c:\Projects\Active\AL10-2.0\al10-server_sqlite\node_modules\has-binary2\index.js:42:87)
at hasBinary (c:\Projects\Active\AL10-2.0\al10-server_sqlite\node_modules\has-binary2\index.js:56:59)
at hasBinary (c:\Projects\Active\AL10-2.0\al10-server_sqlite\node_modules\has-binary2\index.js:56:59)
at hasBinary (c:\Projects\Active\AL10-2.0\al10-server_sqlite\node_modules\has-binary2\index.js:56:59)
at hasBinary (c:\Projects\Active\AL10-2.0\al10-server_sqlite\node_modules\has-binary2\index.js:56:59)
at hasBinary (c:\Projects\Active\AL10-2.0\al10-server_sqlite\node_modules\has-binary2\index.js:56:59)
at hasBinary (c:\Projects\Active\AL10-2.0\al10-server_sqlite\node_modules\has-binary2\index.js:56:59)
at hasBinary (c:\Projects\Active\AL10-2.0\al10-server_sqlite\node_modules\has-binary2\index.js:56:59)
at hasBinary (c:\Projects\Active\AL10-2.0\al10-server_sqlite\node_modules\has-binary2\index.js:56:59)
My Code looks like this:
var express = require("express");
var app = express();
var http = require("http").Server(app);
var Client = require("node-rest-client").Client;
var rest = new Client();
var io = require("socket.io")(http);
var sqlite3 = require("sqlite3");
function test(counter=0, list=[]){
// console.log(counter);
if(list.length == 0 || counter >= list.length){
var query = "SELECT url FROM paths";
db.all(query, (err,data) => {
if(err){
throw (err);
}
test(0, data);
});
}
else{
setTimeout( () => {
GetStatus(list[counter].url, (err, restData) => {
if(err){
/* As soon as one of these are added,
the callstack is exceeded */
// setTimeout(io.sockets.emit("error", err),50);
// io.sockets.emit("error", err);
console.log(err);
}
else{
/* This one is no problem */
io.sockets.emit("status", restData);
console.log(counter + " - " + restData.HeartBeat);
}
// process.nextTick(test, ++counter, list);
test(++counter, list);
});
},1000);
}
}
function GetStatus(url, callback){
var req = rest.get(url, ((data,response) => {
if(response.statusCode == 200){
callback(null,data);
}
else{
callback(response.statusCode,null);
}
}).bind(this));
req.on("error",(function(err){
/* All of the following yeilds the same result */
callback(err,null);
// process.nextTick(callback,err,null);
// setTimeout(callback(err,null),0);
}).bind(this));
}
var db = new sqlite3.Database(":memory:", (err) => {
if(err) return;
});
db.serialize(() => {
var values = ["http://192.168.42.69/restapi/status","http://192.168.42.70/restapi/status"];
db.run("CREATE TABLE paths(url text)")
.run("INSERT INTO paths(url) VALUES (?),(?)", values, (err) => {
if(err){
throw err;
}
test();
});
});
When I add the io.sockets.emit("error",err);
(with or without the setTimeout(...)
) The code fails and gives me the RangeError.
The above code is an isolated test to try to figure out why it does not work. In the real application there are a few more urls and they might change over time. In the real application, this routine will also query the database for changes in the urls every now and again...
I have attempted to implement some of the answers in this post but to no avail.
So my question is, Why does the socket.io call give my a stack overflow? And, how do I get it to work?
I am using
node.js - 8.9.4
socket.io - 2.0.3
sqlite3 - 3.1.13
node-rest-client - 3.1.0
express - 4.15.3