Get node.js to execute local .php file inside pollingLoop - javascript

Short here's the purpose of my application.
I have a PHP file reading data through an ODBC connection and writing them to a local database.
This PHP file needs to be run LOCAL ON THE SERVER each time a loop is processed in my node.js, socket.io server.
My setup is Apache, PHP 5.5.12 and node.js.
I was pretty convinced there was a simple way to this but I haven't had any luck getting Ajax or similar to work inside node.js by following other guides.
The code where the file should be processed inside looks like this.
var pollingLoop = function () {
// Update the local database
// HERE I WANT THE PHP FILE TO EXECUTE
// Make the database query
var query = connection.query('SOME LONG SQL QUERY IN HERE'),
status = []; // this array will contain the result of our db query
// set up the query listeners
query
.on('error', function(err) {
// Handle error, and 'end' event will be emitted after this as well
console.log( err );
updateSockets( err );
})
.on('result', function( runningstatus ) {
// it fills our array looping on each runningstatus row inside the db
status.push( runningstatus );
})
.on('end',function(){
// loop on itself only if there are sockets still connected
if(connectionsArray.length) {
pollingTimer = setTimeout(pollingLoop, POLLING_INTERVAL);
updateSockets({status:status});
}
});
};
Am I totally of track by trying to do that?

Try invoking php through the shell interface:
var exec = require("child_process").exec;
app.get('/', function(req, res){exec("php index.php", function (error, stdout, stderr) {res.send(stdout);});});
OR this link

Related

Separate sessions of the app

I use python script to do some calculations in the backend. The proccess works as follows:
I create a list of variables by clicking on some items in the app
That list is sent to the python script and it sends back a json back
Based on that json file i display a table
Then the list of variables is ereased and I can do this again
But here is the problem, when I run this locally on c9.io, lets say I give the address of that c9.io to someone, then when that person is clicking on variables to add to that list, he adds them to the same list as I do. There are no separate lists for other people when using the app from different ip or something and therefore it gets confusing because when I send to python script I get json file with results i didnt want, but someone else did.
But then Im planning on hosting it on heroku and I wonder if it will be working differently, so when someone is using the app from there he gets his own list of the variables and it wont be shared by everyone who is using this at the same time as someone. Or is there a some way to do this specifically?
Here is the backend code for the app:
First this is the code for adding items to the list and here is the problem since anyone if doing it at the same time will be adding to the same list
var jsondata = ""
var thelist =[]
app.get("/show/:id", function (req, res) {
var id = req.params.id;
thelist.push(id)
console.log(thelist);
res.redirect('/')
});
Then the rest (so running the script and emptying the list)
app.get("/run", function(req, res) {
var pyshell = new PythonShell('script.py');
pyshell.send(JSON.stringify(thelist))
pyshell.on('message', function (message) {
// received a message sent from the Python script (a simple "print" statement)
jsondata += message
});
// end the input stream and allow the process to exit
pyshell.end(function (err) {
if (err){
throw err;
};
console.log(jsondata);
});
thelist = []
});
app.get('/data', function(req, res) {
if (jsondata == "") {
res.redirect('/')
} else {
//viewname can include or omit the filename extension
res.render("data", {data: JSON.parse(jsondata)} )
jsondata = ""}
});
So I think i need those two variables jsondata and thelist need to be somehow coded in a way that they are seprate for every unique user (as in accessing the app from different place, so the app would be run as a separate session for each user that accesses it (but also no need for registration) )

NodeJS getting response from net socket write

I'm trying to get a response from specific requests via the write function.
I'm connected to an equipment via the net module (which is the only way to communicate with it). Currently, I have an .on('data',function) to listen to responses from the said equipment. I can send commands via the write functions to which I am expecting to receive a line of response. How can I go about doing this?
Current code:
server = net.Socket();
// connect to server
server.connect(<port>,<ip>,()=>{
console.log("Connected to server!");
});
// log data coming from the server
server.on("data",(data)=>{
console.log(''+data);
});
// send command to server
exports.write = function(command){
server.write(command+"\r\n");
};
This is a working code. Sending a command to the equipment via server.write returns a response which right now only appears in Terminal. I'd like to return that response right after the write request. Preferably within the exports.write function.
Add a callback argument to your exports.write function can solve your problem.
exports.write = function(command, callback){
server.write(command+"\r\n");
server.on('data', function (data) {
//this data is a Buffer object
callback(null, data)
});
server.on('error', function (error) {
callback(error, null)
});
};
call your write function
var server = require('./serverFilePath')
server.write('callback works', function(error, data){
console.log('Received: ' + data)
})

MongoDB Error: Cannot create property '_id' on string

I'm using Node.js and Express on Heroku, with the MongoDB addon.
My database connection works fine and I can successfully push some data in, but not other.
Here is the database connection:
mongodb.MongoClient.connect(mongoURI, function (err, database) {
if (err) {
console.log(err);
process.exit(1);
}
// Save database object from the callback for reuse.
db = database;
console.log("Database connection ready");
// Initialize the app.
var server = app.listen(process.env.PORT || dbport, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
});
I can successfully push my Twitter API response into the database like this:
db.collection(TWEETS_COLLECTION).insert(data);
('data' is just a JSON variable)
But when I try to push another JSON variable into the database in the same method, I get an error. Code:
var jsonHash = '{"hashtag":"","popularity":1}';
var objHash = JSON.parse(jsonHash);
objHash.hashtag = req.body.hashtag;
JSON.stringify(objHash);
collection(HASHTAG_COLLECTION).insert(jsonHash);
And the error:
TypeError: Cannot create property '_id' on string '{"hashtag":"myhash","popularity":1}'
at Collection.insertMany...
...
Any ideas what I'm doing wrong?
I don't know where you are getting the jsonHash variable from but I think you are doing unecessary JSON-handling here. You are also inserting the wrong variable, you want to insert objHash which is a valid object to insert, now you are inserting jsonHash which is just a string. JSON.stringify(objHash); is not doing anything as you are not saving the JSON returned from the function. I think you want something like this?
var objHash = {
hashtag: "",
popularity:1
};
objHash.hashtag = req.body.hashtag;
collection(HASHTAG_COLLECTION).insert(objHash);
jsonHash is still a string. May be you want to save objHash instead without JSON.stringify ?

Node js. Proper / Best Practice to create connection

Right now i am creating a very large application in Node JS. I am trying to make my code clean and short (Just like most of the developer). I've create my own js file to handle connection to mysql. Please see code below.
var mysql = require('mysql');
var config = {
'default' : {
connectionLimit : process.env.DB_CONN_LIMIT,
host : process.env.DB_HOST,
user : process.env.DB_USER,
password : process.env.DB_PASS,
database : process.env.DB_NAME,
debug : false,
socketPath : process.env.DB_SOCKET
}
};
function connectionFunc(query,parameters,callback,configName) {
configName = configName || "default";
callback = callback || null;
parameters = parameters;
if(typeof parameters == 'function'){
callback = parameters;
parameters = [];
}
//console.log("Server is starting to connect to "+configName+" configuration");
var dbConnection = mysql.createConnection(config[configName]);
dbConnection.connect();
dbConnection.query(query,parameters, function(err, rows, fields) {
//if (!err)
callback(err,rows,fields);
//else
//console.log('Error while performing Query.');
});
dbConnection.end();
}
module.exports.query = connectionFunc;
I am using the above file in my models, like below :
var database = require('../../config/database.js');
module.exports.getData = function(successCallBack){
database.query('SAMPLE QUERY GOES HERE', function(err, result){
if(err) {console.log(err)}
//My statements here
});
}
Using this coding style, everything works fine but when i am trying to create a function that will loop my model's method for some reason. Please see sample below :
for (i = 0; i < 10000; i++) {
myModel.getData(param, function(result){
return res.json({data : result });
});
}
It gives me an ER_CON_COUNT_ERROR : Too Many Conenction. The question is why i still get an error like these when my connection always been ended by this dbConnection.end();? I'm still not sure if i am missing something. I am still stuck on this.
My connection limit is 100 and i think adding more connection is a bad idea.
Because query data form the database is async.
In your loop the myModel.getData (or more precisely the underling query) will not halt/paus your code until the query is finished, but send the query to the database server and as soon as the database response the callback will be called.
The calling end on dbConnection will not close the connection immediately, it will just mark the connection to be closed as soon as all queries that where created with that connection are finished.
mysql: Terminating connections
Terminating a connection gracefully is done by calling the end() method. This will make sure all previously enqueued queries are still before sending a COM_QUIT packet to the MySQL server.
An alternative way to end the connection is to call the destroy() method. This will cause an immediate termination of the underlying socket. Additionally destroy() guarantees that no more events or callbacks will be triggered for the connection.
But with destroy the library will not wait for the result so the results are lost, destroy is rarely useful.
So with your given code you try to create 10000 connections at one time.
You should only use on connection by task, e.g. if a user requests data using the browser, then you should use one connection for this given request. The same is for timed task, if you have some task that is done in certain intervals.
Here an example code:
var database = require('./config/database.js');
function someTask( callback ) {
var conn = database.getConnection();
myModel.getData(conn, paramsA, dataReceivedA)
function dataReceivedA(err, data) {
myModel.getData(conn, paramsB, dataReceivedB)
}
function dataReceivedB(err, data) {
conn.end()
callback();
}
}
If you want to entirely hide your database connection in your model code. Then you would need to doe something like that:
var conn = myModel.connect();
conn.getData(params, function(err, data) {
conn.end();
})
How to actually solve this depends only many factors so it is only possible to give you hints here.

node.js application - how to connect to mongodb and "share" connection via an include?

Background Information
I'm attempting my first node.js API/application. As a learning exercise, I'm trying to create some test cases initially delete all records in a table, insert 3 specific records, and then query for those 3 records.
Code
Here's the code I have cobbled together:
http://pastebin.com/duQQu3fm
Problem
As you can see from the code, I'm trying to put the database connection logic in a dbSession.js file and pass it around.
I am able to start up the http server by doing the following:
dev#devbox:~/nimble_node$ sudo nodejs src/backend/index.js
Server started and listening on port: 8080
Database connection successful
However, when I try to run my jasmine tests, it fails with the following error:
F
Failures:
1) The API should respond to a GET request at /api/widgets/
Message:
TypeError: Object #<MongoClient> has no method 'collection'
Stacktrace:
TypeError: Object #<MongoClient> has no method 'collection'
at resetDatabase (/home/dev/nimble_node/spec/resetDatabase.js:6:29)
at /home/dev/nimble_node/spec/e2e/apiSpec.js:23:25
at /home/dev/nimble_node/node_modules/async/lib/async.js:683:13
at iterate (/home/dev/nimble_node/node_modules/async/lib/async.js:260:13)
at async.forEachOfSeries.async.eachOfSeries (/home/dev/nimble_node/node_modules/async/lib/async.js:279:9)
at _parallel (/home/dev/nimble_node/node_modules/async/lib/async.js:682:9)
at Object.async.series (/home/dev/nimble_node/node_modules/async/lib/async.js:704:9)
at null.<anonymous> (/home/dev/nimble_node/spec/e2e/apiSpec.js:19:9)
at null.<anonymous> (/home/dev/nimble_node/node_modules/jasmine-node/lib/jasmine-node/async-callback.js:45:37)
Finished in 0.01 seconds
1 test, 1 assertion, 1 failure, 0 skipped
Database connection successful
Line 6 of resetDatabase is:
var collection = dbSession.collection('widgets');
Given that after the error appears, I get the "Database connection successful" message, I think what's happening is that when the tests request the dbSession library, the database hasn't finished running the code to connect. And therefore, I can't get the collection object.
I'm currently reading through the mongodb online manual to see if I can find some hints as to how to do something like this.
Any suggestions or pointers would be appreciated.
EDIT 1
To prove that there is a collection method on the MongoClient object, I changed the dbSession.js code to look like this:
'use strict';
var DBWrapper = require('mongodb').MongoClient;
var dbWrapper = new DBWrapper;
dbWrapper.connect("mongodb://localhost:27017/test", function(err, db) {
if (!err) {
console.log("Database connection successful");
dbWrapper = db;
var collection = dbWrapper.collection('widgets');
console.log('just created a collection...');
}
});
module.exports = dbWrapper;
And now, when I start up the http server (index.js), notice the messages:
dev#devbox:~/nimble_node$ sudo nodejs src/backend/index.js
Server started and listening on port: 8080
Database connection successful
just created a collection...
It could be an async issue.
Your code in dbSessionjs
dbWrapper.connect("mongodb://localhost:27017/test", function(err, db) {
if (!err) {
console.log("Database connection successful");
dbWrapper = db;
}
});
module.exports = dbWrapper;
Starts the connection at dbWrapper asynchronously, but exports dbWrapper right away, which is then imported in resetDatabase. Thus yes, the connect function may have not yet returned from the async function when you call it in resetDatabase (and is what the log suggests,as the error appears before the success log).
You could add a callback after dbWrapper.connect() returns, in order to actually only be able to use dbWrapper when the connection finished.
(With sqlite, this may not happen as it accesses the DB faster on the commandline).
This may not be your problem but looks like a candidate.
EDIT: Here's a possible example for a callback, but please take note it depends on what you need to do so there are a lot of different solutions. The key is to call a callback function when you are done initializing.
Another solution could be to simply wait, and/or poll (e.g. chcke a variable 'initialized').
'use strict';
var DBWrapper = require('mongodb').MongoClient;
var dbWrapper = new DBWrapper;
function doConnect(callback) {
console.log("Initializing DB connection...");
dbWrapper.connect("mongodb://localhost:27017/test", function(err, db) {
if (!err) {
console.log("Database connection successful");
dbWrapper = db;
var collection = dbWrapper.collection('widgets');
console.log('just created a collection...');
console.log('calling callback...');
callback(dbWrapper);
} else {
console.log("Error connectingi: " + err);
}
});
};
doConnect(function(correctDbWrapper) {
//Now you can use the wrapper
console.log("Inside callback, now consuming the dbWrapper");
dbWrapper = correctDbWrapper;
var collection = dbWrapper.collection('widgets');
});
It's interesting though I never ran into this issue, although I have generally used similar code like yours. I guess because normally I have this DB initialization right at the top, and then have to do lots of initializations on the node app, which gives the app time enough to return from the connect call....

Categories

Resources