I have written a nice little error reporting middleware, that sits after all the GET and POST handling (after app.use(app.router); ). See below.
This works great for simple quick GET and POST that goes to the PostGIS database etc.
But I have one POST request that is designed to create a bunch of directories, a number of files, and then spawn 1 -> 8 child_processes tasks
childProcess.execFile(job.config.FMEPath, ["PARAMETER_FILE", job.fmeParamFile], { cwd: job.root },
All that setup does not take much time (less than a second, and it is all async (I use the async library at one point to sequence 5 steps (see below).
My issue is error handling. Right now I return a response immediately before creating all the files and doing all the steps. This means that next(err) is not working as expected. What is a good paradigm for reporting back the errors? I am using WINSTON to log errors [logger.log() ], but should I just log the errors on the server, or should I also report it to the original request. here is the current post request (and remember, I would have to keep the rest, and req and next object around for quite a while to be able to call next(err).
exports.build = function (req, res, next) {
var config = global.app.settings.config;
var jobBatch = groupJobs(req.body.FrameList);
var ticket = tools.newGuid("", true);
var fileCount = req.body.FrameList.length * nitfMultiplier;
var ts = timespan.fromSeconds(fileCount / config.TileRate);
var estimate = ts.hours + ":" + tools.pad(ts.minutes, 2) + ":" + tools.pad(ts.seconds, 2);
res.set({ 'Content-Type': 'application/json; charset=utf-8' });
res.send({ ticket: ticket, maxTiles: fileCount, timeEstimate: estimate, tileRate: config.TileRate, wwwURL: config.WWWUrl });
jobBatchRoot(req, res, jobBatch, config, ticket, next);
};
jobBatchRoot() (I will then go off and do a lot of processing, I did not include all that code.
exports.bugs = function (err, req, res, next) {
global.app.settings.stats.errors += 1;
if (err.code == undefined) {
err.code = 500;
err.message = "Server Error";
}
res.status(err.code);
logger.log('error', '%s url: %s status: %d \n', req.method, req.url, err.code, { query: req.query, body: req.body, message: err.message, stack: err.stack });
var desc = req.method + " " + req.url;
var body = util.format("%j", req.body);
var query = util.format("%j", req.query);
var stack = err.stack.split('\n');
res.format({
text: function () {
res.send(util.format("%j", { title: err.message, code: err.code, desc: desc, query: query, message: err.message, stack: err.stack, body: body}));
},
html: function () {
query = tools.pretty(req.query);
res.render('error', { title: err.message, code: err.code, desc: desc, query: query, message: err.message, stack: stack, body: body });
},
json: function () {
res.send({ title: err.message, code: err.code, desc: desc, query: query, message: err.message, stack: err.stack, body: body });
}
});
};
I went and re-factored this. I created a module, with module.exports = function(..) {...}
and then added lots of state and methods to create a class. That contains the Job definition. So now I create the top level directories, return a response, and spawn the sub jobs. They all run async after the express response. But they should not get errors, and if they do, then I use WINSTON to log them in the server, and also return a job done information to the user when all the builds are done.