How do you run RServe on AWS Lambda with NodeJS? - node.js

While this question is quite open-ended, I'm generally trying to follow this excellent post here: https://aws.amazon.com/blogs/compute/analyzing-genomics-data-at-scale-using-r-aws-lambda-and-amazon-api-gateway/ which describes setting up R to run with python. I, on the other hand, am trying to get R to work with NodeJs.
I've packaged up my dependencies, deployed to Lambda, and can run simple Node scripts. However, I am having difficulty connecting to RServe from Node using the npm package Rio (https://www.npmjs.com/package/rio). RServe, on both my localhost and on Heroku, will accept the default connection of 127.0.0.1 and port 6331. No luck with AWS Lambda.
'use strict';
var rio = require('rio');
var Promise = require('bluebird');
var exec = require('child_process').exec;
var whenReady = new Promise(function(resolve){
// require libraries and bootup RServe
exec('Rscript init.R', function(error, stdout, stderr) {
(function check() {
// Attempt to connect to RServe through Rio using my 'up' test function
rio.e({
entrypoint: 'up',
callback: function (err) {
console.log(err);
if (err) return setTimeout(check, 100);
// If no connection error, rserve is running
console.log("Rserve up");
resolve();
}
});
})();
});
});
exports.handler = function(event, context, callback) {
whenReady.then(function () {
// Call hello world
rio.e({
entrypoint: 'hello',
data: {name:'Will'},
callback: function(err, result){
console.log("Error", err);
callback(null, result);
}
});
});
};
This ends with connection refused errors
2017-03-01T22:58:33.210Z 96f69baf-fed2-11e6-9164-e91b9773d645 {
[Error: connect ECONNREFUSED 127.0.0.1:6311] code: 'ECONNREFUSED',
errno: 'ECONNREFUSED', syscall: 'connect', address: '127.0.0.1',
port: 6311 }
Any ideas on how to fix this one? I'm hoping we don't need to get complicated: https://aws.amazon.com/blogs/aws/new-access-resources-in-a-vpc-from-your-lambda-functions/
Thank you in advance!
** Update **
init.R does the following
// Require some libraries
...
require('jsonlite');
up <- function () {
toJSON(TRUE)
}
run.Rserve()
** Last Update **
Gave up and went to the python example as posted in the first link.
Will

Related

getting Error: getaddrinfo ENOTFOUND while performing rest api call in node.js using http.request

i have created api in node.js which consume set of api hosted at http://dev.abc.co.in:20081
not every time but randomly sometimes it throws the error
Error: getaddrinfo ENOTFOUND dev.abc.co.in
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:60:26) {
errno: 'ENOTFOUND',
code: 'ENOTFOUND',
syscall: 'getaddrinfo',
hostname: 'dev.abc.co.in'
}
to call those api i have used request node module because i started getting this error i switched to fetch-node npm module and finally replace the code with internal node module http but getting same error
here is the code i have written using http.request
try{
const options = {
hostname: "dev.abc.co.in",
port : 20081,
path: "/api/entity/workorder",
method: Config.method
};
if(Config.headers){
options.headers = Config.headers
}
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
callback(res, data);
});
req.socket.destroy();
}).on("error", (err) => {
console.log("===Error: ", err);
callback(null, err);
});
if(Config.method!="GET" && Config.body){
Config.headers["Content-Length"] = Config.body.length;
req.write(Config.body);
}
req.end();
}catch(e){
console.log("Exception=====",e);
}
as shown in error message issue related to DNS so i try to resolve this DNS using
node -pe 'require("dns").lookup("dev-vsg.dovertech.co.in",function(){console.dir(arguments)})
but still not resolved.
1) Omit 'http://' from the beginning of your demain and all slashes from the end or any path after the actual domain.
2) Try to resolve your hostname:
const dns = require('dns');
dns.resolve("testdomain.com", 'ANY', (err, records) => {
if (err) {
console.log("Error: ", err);
} else {
console.log(records);
}
});
If dns records has been returned, then you will know it's a node js problem and after that we can investigate further. If not, then it's a domain configuration issue.

Error EADDRNOTAVAIL on socket.send() in node (SSDP protocol)

I'm trying to implement a UPnP discovery service tool (SSDP protocol), I did something similar in python following this post: https://www.electricmonk.nl/log/2016/07/05/exploring-upnp-with-python/ and I would like to port it to node (v. 8.6.0) and typescript however I'm getting the following error when I try to send the message (socket.send(...)):
{ Error: send EADDRNOTAVAIL 239.255.255.250:1900
at Object._errnoException (util.js:1019:11)
at _exceptionWithHostPort (util.js:1041:20)
at SendWrap.afterSend [as oncomplete] (dgram.js:475:11)
code: 'EADDRNOTAVAIL',
errno: 'EADDRNOTAVAIL',
syscall: 'send',
address: '239.255.255.250',
port: 1900 }
I've found a snippet of code for node, that makes this exact thing (https://coolaj86.com/articles/adventures-in-upnp-with-node-js/) and I think that my code is quite equivalent however I cannot see why my code isn't working
const dgram = require('dgram');
const socket = dgram.createSocket('udp4');
let msg_txt = 'M-SEARCH * HTTP/1.1\r\n' +
'HOST:239.255.255.250:1900\r\n' +
'ST:upnp:rootdevice\r\n' +
'MX:2\r\n' +
'MAN:"ssdp:discover"\r\n\r\n';
const message = Buffer.from(msg_txt);
socket.on('message', (msg: Buffer, info: any) => {
console.log(msg.toString());
});
socket.bind({
address: '239.255.255.250',
port: 1900
}, (err) => {
!!err && console.error(err);
});
socket.on('listening', () => {
console.log('Sending msg...');
socket.send(message, 0, message.length, 1900, '239.255.255.250', (err) => {
!!err && console.error(err); // err != null
});
});
I suspect that is a typical one-line-problem but after a while I couldn't find it out, any help is welcome.
I saw it, in node the API is a bit different, the binding should be against the '0.0.0.0' iface and the port 0 (for a random number), so changing the binding command to the following code just fix it:
socket.bind({
address: '0.0.0.0',
port: 0
}, (err) => {
!!err && console.error(err);
});
In python I called to socket.recvfrom() method to get the UPnP devices responses, there is not an explicit socket binding.
For what it's worth, I had a similar setup using Node 10 on Windows and creating a udp4 socket on localhost. Weirdly enough, the setup described in the accepted answer worked on every OS and Node version except Node 10 on Windows in my CI tests. In order to get things to work, I had to explicitly bind to the address localhost instead of 0.0.0.0, like so:
const socket = dgram.createSocket('udp4').unref();
socket.bind({
address: 'localhost',
port: 0
}, (err) => {
!!err && console.error(err);
});

net.Stream is not a constructor - Node Postgres

I'm trying to connect a Node.js app with a PostgreSQL server. It seems that no matter what I use, I end up with the same error:
bundle.js:16177 ERROR: TypeError: net.Stream is not a constructor
at new Connection (bundle.js:10133)
at new Client (bundle.js:9704)
at Object.create (bundle.js:11308)
at Pool._createResource (bundle.js:510)
at Pool.dispense [as _dispense] (bundle.js:498)
at Pool.acquire (bundle.js:573)
at Pool.pool.connect (bundle.js:11359)
at PG.connect (bundle.js:10876)
at bundle.js:1642
At first I was declaring a new pg.Client() like the example in the documentation here, but got the above error discovered that might be a bad idea according to this stack overflow post.
I tried using pg.connect():
var pg = require('pg'); //postgresql dependency
var connectionString = "postgres://postgres:thisissuchagoodpassword#PostgreSQL/localhost:5432/Milestone1DB"
console.log("Initiating...");
//var connectionString = "postgres://postgres:thisissuchagoodpassword#PostgreSQL9.6/localhost:5432/Milestone1DB";
//var client = new pg.Client();
//connect to the database
console.log("Attempting to connect to the database");
pg.connect(function (err, client, done)
{
if(err)
{
console.log("Error connecting to the database.");
throw err;
}
client.query("SELECT DISTINCT state FROM business ORDER BY state", function (err, result)
{
if(err)
{
console.log("Query resulted in an error.");
throw err;
}
console.log(result.rows[0]);
client.end(function (err)
{
if(err)
{
console.log("Error disconnecting from the databse.");
throw err;
}
});
});
});
Here is the pg-promise code that I tried:
var pgp = require('pg-promise');
var cn = {
host: 'localhost', // server name or IP address;
port: 5432,
database: 'Milestone1DB',
user: 'postgres',
password: 'thisissuchagoodpassword'
};
var db = pgp(cn); // database instance;
db.any("select distict state from business order by state;")
.then(data => {
console.log("DATA:", data);
})
.catch(error => {
console.log("ERROR:", error);
});
I must be missing something, but I don't know where to look. Thank you to anyone who can help me figure out what this error means.
Make sure you are not crossing a context boundary that is corrupting the net prototype chain and stripping away methods like Stream(). I ran into a similar unhandled Promise exception w Node 7.5 and pg-live-select. However it was intermittent because of the way the net reference was being passed around. I ended up using V8 inspector and putting a 'debugger' statement directly above line 13 in connection.js to catch the corruption.
node_modules/lib/connection.js:13
this.stream = config.stream || new net.Stream();
^
TypeError: net.Stream is not a constructor
at new Connection (node_modules/pg-live-select/node_modules/pg/lib/connection.js:13:34)
at new Client (node_modules/pg-live-select/node_modules/pg/lib/client.js:26:37)
at Object.create (node_modules/pg-live-select/node_modules/pg/lib/pool.js:27:24)
at Pool._createResource (node_modules/generic-pool/lib/generic-pool.js:325:17)
at Pool.dispense [as _dispense] (node_modules/generic-pool/lib/generic-pool.js:313:12)
at Pool.acquire (node_modules/generic-pool/lib/generic-pool.js:388:8)
at Pool.pool.connect (node_modules/pg-live-select/node_modules/pg/lib/pool.js:78:14)
at PG.connect (node_modules/pg-live-select/node_modules/pg/lib/index.js:49:8)
at LivePg._updateQuery (node_modules/pg-live-select/index.js:295:6)
at node_modules/pg-live-select/index.js:160:14
at Array.forEach (native)
at Timeout.performNextUpdate [as _onTimeout] (node_modules/pg-live-select/index.js:159:23)
at ontimeout (timers.js:365:14)
at tryOnTimeout (timers.js:237:5)
at Timer.listOnTimeout (timers.js:207:5)

Webshot fails on Meteor in DigitalOcean Ubuntu 14.04

I am using this code to generate pdf:
let fileUri = process.env.PWD + '/storage/orders-pdf/' + fileName;
// Commence Webshot
webshot(html_string, fileUri, options, function(error) {
fs.readFile(fileUri, function (err, data) {
if (err) {
return console.log(err);
}
fs.unlinkSync(fileUri);
fut.return(data);
});
});
let pdfData = fut.wait();
But it throws the following error:
{ [Error: ENOENT, open '/opt/holi/storage/orders-pdf/Attributes.pdf']
errno: 34,
code: 'ENOENT',
path: '/opt/holi/storage/orders-pdf/Attributes.pdf' }
Tried to use npm package https://github.com/brenden/node-webshot
Then code works perfectly on localhost, but fails on the server and throws this error:
EDIT:
Even when running webshot without:
fs.readFile(fileUri, function (err, data) {
if (err) {
return console.log(err);
}
fs.unlinkSync(fileUri);
fut.return(data);
});
The file is not created..
EDIT-2:
Webshot throws an error: [Error: PhantomJS exited with return value 2]
EDIT-3:
Actual issue: https://github.com/brenden/node-webshot/issues/123
I had a similar problem, and spent most of the day trying to figure out the issue. I ended up adding:
"phantomPath": "/usr/bin/phantomjs"
to my webshot options object. The phantom path I used is where mup installs phantomjs on your server setup.

Error using Redis Multi with nodejs

I am using Redis and consulting it from nodejs, using the module Redis.
When i exec a client.multi() and the redis server is down the callback doesn't send the error and the nodejs app terminates.
This is the error
/Users/a/db/node_modules/redis/index.js:151
throw callback_err;
^
TypeError: Cannot read property 'length' of undefined
at Command.callback (/Users/a/db/node_modules/redis/index.js:1098:35)
at RedisClient.flush_and_error (/Users/a/db/node_modules/redis/index.js:148:29)
at RedisClient.on_error (/Users/a/db/node_modules/redis/index.js:184:10)
at Socket.<anonymous> (/Users/a/db/node_modules/redis/index.js:95:14)
at Socket.EventEmitter.emit (events.js:95:17)
at net.js:441:14
at process._tickCallback (node.js:415:13)
this is my code:
Constructor class
var redis = require('redis');
var client;
function Redis(){
client = redis.createClient();
client.on("error", function (err) {
console.log("Error " + err);
});
}
Redis.prototype.multi = function(commands,callback){
var err = null;
client.multi(commands).exec(function (error, res) {
if(error){
process.nextTick(function(){
callback(error,null)
})
}else{
process.nextTick(function(){
callback(null,res)
})
}
});
}
FYI, I ran across this in an old lib that depended on old version of node_redis.
This issue was a bug and was fixed in v0.9.1 - November 23, 2013: https://github.com/mranney/node_redis/pull/457
I think that people are still reaching here... (not sure if this answers this specific question directly, but I assume people reaching here since the multi.exec() returns true / the event loop is not waiting for it's response.
After the fixes that went in (in node-redis), it is possible to wrap the result of exec with Promise, and then you will be sure that the result will include the replies from the multi.
So, you can add some redis commands to the multi:
await multi.exists(key);
await multi.sadd(key2,member);
And then in the result do something like:
return new Promise((resolve, reject) => {
multi.exec((err, replies) => {
if (err) {
reject(err);
}
return resolve(replies);
});
});
Otherwise, if you will just do: const reply = await multi.exec();
it will just return you true, and not the replies
** Important to mention - this refers to 'async-redis' and 'node-redis'

Resources