From 7176371e85bb582e7321658609d24c3406a44206 Mon Sep 17 00:00:00 2001 From: prasad83 Date: Wed, 15 Mar 2017 12:48:53 +0530 Subject: [PATCH 1/3] Callback invoked multiple-times from call function. When stderr and stdout gets data callback function get invoked twice. Devised following fix along with #6 --- index.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index f43b588..000b642 100644 --- a/index.js +++ b/index.js @@ -29,9 +29,21 @@ R.prototype.call = function(_opts, _callback) { var opts = _.isFunction(_opts) ? {} : _opts; this.options.env.input = JSON.stringify([this.d, this.path, opts]); var child = child_process.spawn("Rscript", this.args, this.options); - child.stderr.on("data", callback); + var body = { + out: "", + err: "", + }; + child.stderr.on("data", function(d){ + body.err += d; + }); child.stdout.on("data", function(d) { - callback(null, JSON.parse(d)); + body.out += d; + }); + child.stderr.on("end", function(){ + if (body.err) callback(new Error(body.err.toString())); + }) + child.stdout.on("end", function() { + if (!body.err) callback(null, JSON.parse(body.out)); }); }; From 00e0b1a547dd7b6caefce9274873237cdb0b8f98 Mon Sep 17 00:00:00 2001 From: prasad83 Date: Wed, 15 Mar 2017 13:04:38 +0530 Subject: [PATCH 2/3] Handled filtering of Error specifically. --- index.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index 000b642..3ccec2e 100644 --- a/index.js +++ b/index.js @@ -29,10 +29,7 @@ R.prototype.call = function(_opts, _callback) { var opts = _.isFunction(_opts) ? {} : _opts; this.options.env.input = JSON.stringify([this.d, this.path, opts]); var child = child_process.spawn("Rscript", this.args, this.options); - var body = { - out: "", - err: "", - }; + var body = { out: "", err: "", }; child.stderr.on("data", function(d){ body.err += d; }); @@ -40,8 +37,13 @@ R.prototype.call = function(_opts, _callback) { body.out += d; }); child.stderr.on("end", function(){ - if (body.err) callback(new Error(body.err.toString())); - }) + // NOTE: Warning or Info messages get caught in stderr! + if (body.err) { + body.err = body.err.toString(); + if (body.err.indexOf('Error ') != -1) callback(new Error(body.err)); + else body.err = null; // To let the stdout be sent to callback. + } + }); child.stdout.on("end", function() { if (!body.err) callback(null, JSON.parse(body.out)); }); From 427825309b0f0c197013a9c51a688b0696b3324c Mon Sep 17 00:00:00 2001 From: prasad83 Date: Fri, 31 Mar 2017 12:59:46 +0530 Subject: [PATCH 3/3] Timeout option to terminate long running script. Having timeout option to terminate long running script is useful when making the call. --- index.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 3ccec2e..a3e5ee4 100644 --- a/index.js +++ b/index.js @@ -29,7 +29,14 @@ R.prototype.call = function(_opts, _callback) { var opts = _.isFunction(_opts) ? {} : _opts; this.options.env.input = JSON.stringify([this.d, this.path, opts]); var child = child_process.spawn("Rscript", this.args, this.options); - var body = { out: "", err: "", }; + var body = { out: "", err: "", timeout: false}; + if (_opts.timeout) { + setTimeout(function(){ + child.stdin.pause(); // Required to make sure KILL works + child.kill(); + body.timeout = true; + }, _opts.timeout); + } child.stderr.on("data", function(d){ body.err += d; }); @@ -45,6 +52,7 @@ R.prototype.call = function(_opts, _callback) { } }); child.stdout.on("end", function() { + if (body.timeout) callback(new Error('Too long run... terminated')); if (!body.err) callback(null, JSON.parse(body.out)); }); };