mjwrazor
mjwrazor

Reputation: 1964

Is there a way to shutdown Nodejs and restart my app from scratch?

The app needs to completely die so I don't end up with multiple node processes running. I need to kill node but I also need to start up a new node. Npm start would be great because it calls gulp and rebundles the project.

Is there a simple way to do this. Right now I have a route that calls process.exit() but it returns

[nodemon] clean exit - waiting for changes before restart

EDIT

What I mean from scratch is to git pull, re-bundle and then start node again.

EDIT 2

@Paul .. Well actually I have an API I call from a specific page that uses simple-git and pulls from the master branch. This will only send a message to the user there is an update. And another route I have is process.exit(0). Right now i have it set up in a singular cluster so one master one worker. This doesn't seem to work.

I am a little confused on how I would use the detached spawn process. I need to run gulp, which will bundle everything and then start app.js. However with my singular cluster it seems to get a net:: ERR_EMPTY_RESPONSE every so often which is not acceptable. This is just something I have never dealt with before and haven't seen anyone else do this.

Edit 3.

I ended up taking out the cluster code and running it and it seems to be working were it rebundles. Although no node restart. I don't believe we need a node restart but I will definitely look into how to do that still.

Upvotes: 0

Views: 581

Answers (3)

mjwrazor
mjwrazor

Reputation: 1964

I ended up solving the issue with the help of @Paul who had some pointers that lead me in the right direction.

What we ended up doing.

in app.js > the server This is made to search git for an update and flip a boolean

var isUpdate = false;
var checkUpdate = function(){
  simpleGit.pull(function(err, data){
    if(data && data.summary.changes){
      isUpdate = true;
    }
  });
  return isUpdate;
};
// if true is sent then /api/reboot will be called from the client
router.get('/api/update', function (req, res) {
  res.json({isUpdate: checkUpdate()});
});
// reboot client
router.get('/api/reboot', function (req, res) {
  process.exit(0);
});

gulps default and tasks called

// Easy to understand but will show start
gulp.task('default', function(callback) {
  runSequence('bundle', 'chrome', 'start', callback);
});
// Launch node process
function boot() {
  return exec('node app.js', function (err, stdout, stderr) {
    console.log(stdout);
    console.log(stderr);
  }).on('exit', function () {
    runSequence('bundle', boot);
  });
}
// Launches server and auto-updates
gulp.task('start', function(cb){
  boot()
});

On the client I ran an interval to check for an update when there was I asked the user to update and when they say yes a reboot is sent. I then tell the user to wait for a second while the update finishes and then I reload the page with.

$window.location.reload();

Inside of a timeout of course so the user has time to read the message about what version they are on.

Upvotes: 0

Paul
Paul

Reputation: 36329

If you're already using grunt, checkout grunt-watch and point it at a canary file or the installed directory and it'll do what you ask.

UPDATE

So, I didn't grok from the first version of the question that you're trying to get the Node app to actually know when it needed to be "replaced". That will require some kind of polling or check. The right way to do this depends a great deal on your architecture, but in general if you have a bunch of installs you don't own (e.g. stuff other people have installed like a shell app or something) you can have your app poll some resource (perhaps even your git repo or NPM itself, depending on where the code is hosted) to see what the latest tagged version is. As a rule, I wouldn't "auto update" on every tag, instead I'd have something that notifies the user that it needs to be updated, and only action by the user gets it to happen, if there are users who will be affected.

That said, once the app knows it should be replaced, it should not just overwrite itself. Instead, what I would do is git checkout the new tag to another folder (maybe you have folders based on version names), then run the build process there. Some kind of verification at that point is a good idea; make sure the files downloaded correctly and the build ran as expected. If all went to plan, I would then have it shut itself down and start up the app in the new path. I'd probably do it by spawning the new process in a detached state so that the other one can exit without error after it's done calling that.

How to detach a spawned child process in a Node.js script?

If you're talking all about instances of the app you own, I'd probably do a blue/green deployment instead, but this is running long and your question isn't clear on which scenario(s) you're trying to support.

Upvotes: 1

Abacus
Abacus

Reputation: 19431

You might want to check pm2 which gives you the ability to start/stop/restart a node process.

Upvotes: 1

Related Questions