I have an application that I am writing in Node.js that has to handle a lot of configuration requests and databases to process user data. The problem I am facing is that after 11,800+ function calls, Node will throw an error and exit the process.
The error says: RangeError: maximum call stack size exceeded
I am curious if anyone else has such a situation, and know how they handle this. I have already started breaking my code into several additional working files, but every time I process Node data, it should touch 2 databases (no more than 25 calls to update various tables) and perform a number of sanitary checks.
I fully agree to admit that I might be doing something suboptimal if that is the case, but it would be helpful if there would be a better guide.
Here is an example of the code that I run for the data:
app.post('/initspeaker', function(req, res) { // if the Admin ID is not present ignore if(req.body.xyzid!=config.adminid) { res.send( {} ); return; } var gcnt = 0, dbsize = 0, goutput = [], goutputdata = [], xyzuserdataCallers = []; xyz.loadbatchfile( xyz.getbatchurl("speakers", "csv"), function(data) { var parsed = csv.parse(data); console.log("lexicon", parsed[0]); for(var i=1;i<parsed.length;i++) { if(typeof parsed[i][0] != 'undefined' && parsed[i][0]!='name') { var xyzevent = require('./lib/model/xyz_speaker').create(parsed[i], parsed[0]); xyzevent.isPresenter = true; goutput.push(xyzevent); } } dbsize = goutput.length; xyzuserdataCallers = [new xyzuserdata(), new xyzuserdata(), new xyzuserdata(), new xyzuserdata(), new xyzuserdata(), new xyzuserdata(), new xyzuserdata(), new xyzuserdata() ]; // insert all Scheduled Items into the DB xyzuserdataCallers[0].sendSpeakerData(goutput[0]); for(var i=1;i<xyzuserdataCallers;i++) { xyzuserdataCallers[i].sendSpeakerData(8008); } //sendSpeakerData(goutput[0]); }); var callback = function(data, func) { //console.log(data); if(data && data!=8008) { if(gcnt>=dbsize) { res.send("done"); } else { gcnt++; func.sendSpeakerData(goutput[gcnt]); } } else { gcnt++; func.sendSpeakerData(goutput[gcnt]); } }; // callback loop for fetching registrants for events from SMW var xyzuserdata = function() {}; xyzuserdata.prototype.sendSpeakerData = function(data) { var thisfunc = this; if(data && data!=8008) { //console.log('creating user from data', gcnt, dbsize); var userdata = require('./lib/model/user').create(data.toObject()); var speakerdata = userdata.toObject(); speakerdata.uid = uuid.v1(); speakerdata.isPresenter = true; couchdb.insert(speakerdata, config.couch.db.user, function($data) { if($data==false) { // if this fails it is probably due to a UID colliding console.log("*** trying user data again ***"); speakerdata.uid = uuid.v1(); arguments.callee( speakerdata ); } else { callback($data, thisfunc); } }); } else { gcnt++; arguments.callee(goutput[gcnt]); } }; });
A couple of classes and elements that need to be introduced are described here:
- I am using Express.js + hosted by CouchDB and this responds to a POST request.
- There is a CSV parser class that loads a list of events that drive speaker data.
- Each event can contain n users (currently about 8K users for all events)
- I use a template that loads all data / users before trying to parse them.
- Each loaded by the user (external data source) is converted into an object that I can use, as well as disinfect (slashes, etc.)
- Each user is then inserted into CouchDB
This code works in the application, but after a while I get an error that more than 11 800 + calls were made, and the application breaks. This is not an error that contains a stack trace, as if it were a code error, it exits due to the number of calls made.
Again, any help / comment / direction would be appreciated.