KLôN KLôN - 4 months ago 22
Node.js Question

Scaffolding a Node.js app properly without Express (the app doesn't receive requests)

[This question is quite vague, I apologize for it. I'm trying to address my various troubles by answering the question myself]

I am building a Node.js app which has to perform various tasks at given intervals. Here is the global scaffold (involves bluebird promises and mongoose for DB interactions) :



var Promise = require("bluebird");
var mongoose = require('mongoose');
mongoose.Promise = require('bluebird');

// Personal modules
var bootApp = require(...);
var doStuffA = require(...);
var doStuffB = require(...);
var doStuffC = require(...);

// running locally, but meant to be deployed at some point
mongoose.connect('mongodb://localhost:27017/myDatabase');
var db = mongoose.connection;

db.on('error', () => {
console.log("Error : lost connection !"));
process.exit(1);
});

db.once('open', () => {

bootApp() // always start by booting
.then( () => { // then start the infinite loop of events

setInterval(doStuffA, 1000*60*60); // 1x/1h
setInterval(doStuffB, 1000*60*10); // 1x/10min
setInterval(doStuffC, 1000*60*3); // 1x/3min

}).catch((e) => { // errors are handled by doStuffX(), so we should never catch anything here
console.log(e.message);
process.exit(1);
});
});





Each module
doStuffX
is a function returning a Promise, handling its own errors, and should finish at some point.

Expected behaviour for the entire app :


  • The app should be able to run forever

  • The app should try to
    doStuffX()
    at the given interval, regardless of whether it succeeded or failed last time.

  • [Optional :] The app should close smoothly without retrying any
    doStuff
    upon receiving a "shut down" signal.



My question : how to build a clean scaffold for such an app ? Can I get rid of
setInterval
and use promises instead ? One of my main concerns is to make sure the previous instance of
doStuffX()
is finished before starting the next one, even if it involves "killing" it in some way.

I am open to any link about scaffolding apps, but PLEASE DO NOT GIVE ME AN ANSWER/LINK INVOLVING EXPRESS : I don't need Express, since my app doesn't receive any request. (everything I found so far starts with Express :/)

Answer

If you don't want to start the next doStuffX() until the previous one is done, then you can replace your setInterval() with repeated setTimeout() calls.

function runA() {
    setTimeout(function() {
        doStuffA().then(runA).catch(function(err) {
            // decide what to do differently if doStuffA has an error
        });
    }, 1000*60*60);
}

runA();

You could also add a timeout to this so that if doStuffA() doesn't respond within a certain amount of time, then you take some other action. This would involve using another timer and a timeout flag.

Comments