1

I have an Mean application which uses nodejs, angularjs and expressjs.

Here I have called my server from the angular controller as below

Angular Controller.js

     $http.post('/sample', $scope.sample).then(function (response) {

         --
         --     
        }

and in Server.js as below

app.post('/sample', userController.postsample);

Here I am doing my operation with mongodb in that post sample from above code.

Here I got struck how to do my calculation part like I have a big calculation which takes some time (assume 1 hour) to complete. So from client side I will trigger that calculation from my angular controller.

My problem is that calculation should run in separately so that other UIs and operations of other pages should not be interupted.

I had seen that child process in nodejs but I didn't understand how to trigger or exec that from child process from controller and if it get request in app.post then is it possible to access other pages.

EDIT:

I have planned to do in Spawn a child_process but I have another problem continuing the above.

Lets consider application contains 3 users and 2 users are accessing the application at same time. My case is If first person triggered the child_process name it as first operation and it is in process and at that moment when second person need to trigger the process name it as 2nd operation as he also needed to calculate. Here my questions are

  1. What happens if another person started the spawn command. If it hangs or keep in queue or both execute parallel.
  2. If 2nd operation is in queue then when it will start the operation.
  3. If 2nd operation is in queue then how can i know how many are in queue at a point of time

Can anyone help to solve.

charan tej
  • 1,054
  • 10
  • 29
  • I would rather have two server routes: ``` POST /sample GET /sample-end ``` The first one will do the computation and the second one will do: - computation is not done -> return a message saying not yet - computation is donte -> return the result. Your controller is already separated from the UI. From time to time, call the second route. – Pierre R-A Apr 06 '17 at 14:47

1 Answers1

1

Note: the question was edited - see updates below.

You have few options to do it.

The most straightforward way would be to spawn the child process from your Express controller that would return the response to the client once the calculation is done, but if it takes so long then you may have problems with socket timeouts etc. This will not block your server or the client (if you don't use "Sync" function on the server and synchronous AJAX on the client) but you will have problems with the connection hanging for so long.

Another option would be to use WebSocket or Socket.io for those requests. The client could post a message to the server that it wants some computation to get started and the server could spawn the child process, do other things and when the child returns just send the message to the client. The disadvantage of that is a new way of communication but at least there would be no problems with timeouts.

To see how to combine WebSocket or Socket.io with Express, see this answer that has examples for both WebSocket and Socket.io - it's very simple actually:

Either way, to spawn a child process you can use:

  • spawn
  • exec
  • execFile
  • fork

from the core child_process module. Just make sure to never use any functions with "Sync" in their name for what you want to do because those would block your server from serving other requests for the entire time of waiting for the child to finish - which may be an hour in your case, but even if it would be a second it could still ruin the concurrency completely.

See the docs:

Update

Some update for the edited question. Consider this example shell script:

#!/bin/sh
sleep 5
date -Is

It waits for 5 seconds and prints the current time. Now consider this example Node app:

let child_process = require('child_process');

let app = require('express')();

app.get('/test', (req, res) => {
  child_process.execFile('./script.sh', (err, data) => {
    if (err) {
      return res.status(500).send('Error');
    }
    res.send(data);
  });
});

app.listen(3344, () => console.log('Listening on 3344'));

Or using ES2017 syntax:

let child_process = require('mz/child_process');

let app = require('express')();

app.get('/test', async (req, res) => {
  try {
    res.send((await child_process.execFile('./script.sh'))[0]);
  } catch (err) {
    res.status(500).send('Error');
  }
});

app.listen(3344, () => console.log('Listening on 3344'));

It runs that shell script for requests on GET /test and returns the result.

Now start two requests at the same time:

curl localhost:3344/test & curl localhost:3344/test & curl localhost:3344/test &

and see what happens. If the returned times differ by 5 seconds and you get one response after another with 5 seconds intervals then the operations are queued. If you get all responses at the same time with more or less the same timestamp then those are all run in parallel.

Sometimes it's best to make an experiment like this to see what happens.

rsp
  • 107,747
  • 29
  • 201
  • 177
  • How can we get details from mongodb in child page and send to main page to print on console. Please look at http://stackoverflow.com/questions/43490211/how-to-fetch-the-details-from-mongo-db-and-send-or-store-in-object-in-nodejs-for – charan tej Apr 19 '17 at 08:28