I am implementing a very basic website using nodejs, and expressjs framework. The idea is that the user enters the website, click on a button that will trigger a cpu-intensive task in the server, and get a message on the browser upon the completion of the task.
The confusing part for me is how to accomplish this task for each user without blocking the event-loop, thus, no user has to wait for another to finish. Also, how to use a new instance of the used resources(objects, variables..) for each user.
After playing and reading around, I have come across child-process. Basically, I thought of forking a new child_process for each user so that whatever the time the sorting takes, it won't block my event-loop. However, I am still not sure if this is the best thing to do for such a scenario.
Now, I have done what I wanted to but with only single user, however when trying to start another user, things become messy and variables are shared. I know that I should not use global variables declared in the module, but what could be another way to make variables shared among functions within a single module yet they are different for each user!?
I know that the question may sound very basic, but I kinda miss the idea of how does node js serve different users with new variables, objects that are associated with each individual user.
In short, my questions are: 1- how does node serve multiple users simultaneously? 2- when and how should I resort to forking or executing a new child-process under the hood, and is it for each user or based on my # cores in cpu 3- how to separate resources in my application for each user such that each user has his own counters, emails and other objects and variables. 4- when do I need or I have to kill my child process.
Thanks in advance.
CODE:
var cp = require('child_process');
var child= cp.fork('./routes/mysort-module');
exports.user=function(req,res){
// child = new cp.fork('./routes/mysort-module'); // Should I make new child for each user?
child.on('message',function(m){ res.send('DONE');}
child.send('START PROCESS'); // Forking a cpu-intensive task in mysort-module.js
}
IN MY SORTING MODULE:
var variables = require(...);
//GLOBAL VARIABLES to be shared among different functions in this module
process.on('message',function(m){
//sort cpu-intensive task
process.send('DONE');
});
// OTHER FUNCTIONS in THE MODULE that make use of global variables.
You should try to split up your question. However, I hope this answers it.
Question 1: A global variable is not limited to request scope. That's a part of Node's definition for a global and it doesn't make sense to enforce this somehow. You shouldn't use globals at all.
The request scope is given by the HTTP module:
http.createServer(function(req, res) {
var a = 1;
// req, res, and a are in request scope for your user-associated response
});
Eliminating globals shouldn't be that hard: If module A and B share a global G and module C calls A.doThis() and B.doThat(), change C to call A.doThis(G) and B.doThat(G) instead. Do this for all occurrences of G and reduce its scope to local or request.
Additionally, have a look for "Sessions", if you need a scope coverig multiple requests from one client.
Question 2: Start the child process inside the request handler:
exports.user = function(req,res){
child = new cp.fork('./routes/mysort-module');
Question 3: See question 1?
Question 4: After the process returned the calculated results.
process.on('DONE', function(result) {
process.exit();
// go on and send result to the client somehow...
});