How to terminate MongoClient.connect after executing its callback? - javascript

The following code inserts a new document,{name:'r2'}, as desired.
How can it be modified to terminate?
var MongoClient = require ('mongodb').MongoClient;
MongoClient.connect ('mongodb://localhost:27017/dbA', function (err, db) {
if (err) {
console.log (err);
} else {
var collection = db.collection ('colA');
collection.insert ({name: 'r2'});
} // end if (err)
});

To kill it after performing the insert, I added lines after the if clause to autokill the program after the insertion is done.
var MongoClient = require ('mongodb').MongoClient;
MongoClient.connect ('mongodb://localhost:27017/dbA', function (err, db) {
if (err) {
console.log (err);
} else {
var collection = db.collection ('colA');
collection.insert ({name: 'r7'});
} // end if (err)
var exec = require ('child_process').exec;
var ppath = process.argv[1];
// trim leading path up to the last '/'
var matched = ppath.match ('.*/(.*)');
var pName = matched [1];
//console.log ('pName: ' + pName);
var killCmd = 'kill -9 `ps -ef | grep ' + pName + ' | grep -v grep | perl -lpe ' + "'" + 's/\\w+\\s+(\\d+).*/$1/' + "'" + '`';
//console.log ('killCmd: ' + killCmd);
exec (killCmd);
});

Related

JS await not working as expected with pg query

I want to use the return of a query to a postgresSQL database. I don't want to just print it. I want to use it in another function. The problem is that the function here returns before it is finished with executing the code.
async function create_base_config(user_id, service_id, timer_seconds) {
var ret
var line
await db_adm_conn.query(`
INSERT INTO base_config (user_id, service_id, timer_seconds)
VALUES ('` + user_id + "', '" + service_id + "', '" + timer_seconds + "') RETURNING id;", (err, result) => {
if (err) {
ret = false
line = err
console.log("line2 err : " + line)
}
else {
ret = true
line = result.rows
console.log("line2 : " + line)
// json_return = JSON.parse(result)
// console.log(result.rows)
}
});
console.log("line: " + line)
return { ret_value: ret, line_value: line };
}
To test it i inserted debug prints. The output is:
server_1 | line: undefined
server_1 | line2 : [object Object]
so I am exectuting the code after the await before the await is finished. How can i fix that, so that he first executes all the code from the await and then the rest?
you should not use a callback function as the arrow function. You should use try catch like this:
async function create_base_config(user_id, service_id, timer_seconds) {
var ret
var line
try {
line = await db_adm_conn.query(`
INSERT INTO base_config (user_id, service_id, timer_seconds)
VALUES ('` + user_id + "', '" + service_id + "', '" + timer_seconds + "') RETURNING id;")
ret = true
}
catch (err) {
ret = false
line = err
}
return { ret_value: ret, line_value: line };
}

Chaining in EventEmitters in JavaScript and calling emitter.emit() before emitter.on()

In an example the event.on() was called after event.emit() method but still the results appeared. I know that some wehre it is related to chaining but can anyone explain the chaining and the cause why the order of operations isn't a concern in the example
var EventEmitter = require('events').EventEmitter;
var fs = require('fs');
function findPattern(files, regex) {
var emitter = new EventEmitter();
files.forEach(function(file) {
fs.readFile(file, 'utf8', function(err, content) {
if(err)
return emitter.emit('error', err);
emitter.emit('fileread', file);
var match = null;
if(match = content.match(regex))
match.forEach(function(elem) {
emitter.emit('found', file, elem);
}); });
});
return emitter;
}
findPattern(
['fileA.txt', 'fileB.json'],
/hello \w+/g
)
.on('fileread', function(file) {
console.log(file + ' was read');
})
.on('found', function(file, match) {
console.log('Matched "' + match + '" in file ' + file);
})
.on('error', function(err) {
console.log('Error emitted: ' + err.message);
});

NJS-024: memory allocation failed in OracleDB - Nodejs

I am trying to run a query using OracleDB with Nodejs to get the view populated in the UI but I get a NJS-024: memory allocation failed error. Can someone help me out? The view contains 120 columns in total and when I query the view in SQL Developer, it works just fine.
ConnectionPool.js:
var path = require('path');
var oracledb = require('oracledb');
var poolMap = {};
var logger = require(path.join(global.root + '/app/util/logger.js'))();
function createPool(poolName, config, callback) {
oracledb.createPool(
config,
function(err, p) {
if (err){
logger.error(err);
return;
}
poolMap[poolName] = p;
callback(poolMap[poolName]);
}
);
}
function getPool(poolName) {
return poolMap[poolName];
}
module.exports = {
createPool: createPool,
getPool: getPool
};
This is my poolAttributes:
var pool;
oracledb.prefetchRows = 10000;
oracledb.maxRows = 400000;
var poolAttrs = {
user: dbcfg.username,
password: dbcfg.password,
connectString: dbcfg.connectionString,
connectionClass : 'Report API',
poolMin : 3,
poolMax : 10,
poolIncrement: 2,
poolTimeout : 600 //seconds
};
connectionPool.createPool("Reports", poolAttrs, function(connPool){
pool = connPool;
logger.info("Pool created by reports.");
});
This is my code:
router.post('/report/', jsonParser, function (req, res) {
var data = req.body,
startRow = data.startRow,
numRows = data.numRows,
sortCol = data.sortCol,
sortDir = data.sortDir;
var countQuery = 'SELECT COUNT(*) ' +
'FROM this_view ' ;
var query = 'SELECT * ' +
'FROM this_view' ;
var seg,
orderBy,
offset;
orderBy = ' ORDER BY UPPER(' + sortCol + ') ' + sortDir;
offset = ' OFFSET ' + startRow + ' ROWS FETCH NEXT ' + numRows + ' ROWS ONLY';
query += orderBy;
query += offset;
logger.info("Begin: " + (new Date().toString()));
async.parallel({
rows: function (callback) {
pool.getConnection(function (err, connection) {
logger.info("Begin Connection: " + (new Date().toString()));
if (err) {
logger.error(err.message);
return;
}
logger.info("Begin execute: " + (new Date().toString()));
connection.execute(
query,
{},
{
resultSet: true,
prefetchRows: 1000
},
function (err, results) {
logger.info("End execute: " + (new Date().toString()));
var rowsProcessed = 0;
var startTime;
if (err) {
logger.error(err.message);
callback("Something broke in the first thing");
doRelease(connection);
return;
}
var procJson = [];
function fetchRowsFromRS(connection, resultSet, numRows) {
resultSet.getRows(
numRows, // get this many rows
function (err, rows) {
if (err) {
console.error(err);
doClose(connection, resultSet); // always close the result set
} else if (rows.length >= 0) {
/**
* For each row in the result, pushes a new object to the rows array
* In each new object, the key is assigned and the result row value set
*/
for (var i = 0; i < rows.length; i++) {
procJson.push({});
console.log(procJson);
for (var j = 0; j < resultSet.metaData.length; j++) {
procJson[i][resultSet.metaData[j].name.toLowerCase()] = rows[i][j];
}
}
//TODO: Add null handling
logger.info("Send JSON: " + (new Date().toString()));
logger.info("JSON Sent: " + (new Date().toString()));
if (rows.length === numRows) // might be more rows
fetchRowsFromRS(connection, resultSet, numRows);
else
doClose(connection, resultSet); // always close the result set
} else { // no rows
doClose(connection, resultSet); // always close the result set
}
});
}
fetchRowsFromRS(connection, result.resultSet, numRows);
callback(null, procJson);
});
});
},
totalRows: function (callback) {
pool.getConnection(function (err, connection) {
logger.info("Begin Connection: " + (new Date().toString()));
if (err) {
logger.error(err.message);
return;
}
logger.info("Begin execute: " + (new Date().toString()));
connection.execute(
countQuery,
function (err, result) {
logger.info("End execute: " + (new Date().toString()));
if (err) {
logger.error(err.message);
callback("Something broke");
doRelease(connection);
return;
}
logger.info("Send JSON: " + (new Date().toString()));
console.log(result.rows);
callback(null, result.rows[0][0]);
logger.info("JSON Sent: " + (new Date().toString()));
doRelease(connection);
});
});
}
}, function(err, result){
if(err){
logger.error(err);
}
res.send(result);
});
});
If rows.length >=0 and if the query returns 0 results, I get this.
How much memory does your Node.js server have? You're setting maxRows very high and grabbing all the data in a single shot. This is likely causing you to run out of memory. Generally, the key is to balance round trips (which you want to reduce) with memory usage (which goes up as round trips are reduced.
You'll want to leverage the ResultSet API, which allows you to stream a read-consistent view of data in smaller chunks. Have a look at this for ideas: https://jsao.io/2015/07/an-overview-of-result-sets-in-the-nodejs-driver/
Rather than buffer the data in the Node.js server (which would lead to the same problem), you'll want to stream it down to the http request.
Finally, but perhaps most importantly, note that your code is currently open to SQL injection. Values that come in from users via req.body cannot be trusted. They must either be bound in using bind variables OR sanitized using something like dbms_assert.
Only values (like numRows) can be bound in. Identifiers (like sortCol) have to be sanitized. You'll likely want to do the sanitization in Node.js, so here's a really basic check that should help.
You could create an "assert" module:
function simpleSqlName(name) {
if (name.length > 30) {
throw new Error('Not simple SQL');
}
// Fairly generic, but effective. Would need to be adjusted to accommodate quoted identifiers,
// schemas, etc.
if (!/^[a-zA-Z0-9#_$]+$/.test(name)) {
throw new Error('Not simple SQL');
}
return name;
}
module.exports.simpleSqlName = simpleSqlName;
function validSortOrder(order) {
if (order !== 'desc' && order !== 'asc') {
throw new Error('Not valid sort order');
}
return order;
}
module.exports.validSortOrder = validSortOrder;
Then your code would look more like this (notice I'm using both the assert module and bind variables):
let assert = require('assert.js');
router.post('/report/', jsonParser, function (req, res) {
var data = req.body,
startRow = data.startRow,
numRows = data.numRows,
sortCol = assert.simpleSqlName(data.sortCol),
sortDir = assert.validSortOrder(data.sortDir);
var countQuery = 'SELECT COUNT(*) ' +
'FROM this_view ' ;
var query = 'SELECT * ' +
'FROM this_view' ;
var seg,
orderBy,
offset;
orderBy = ' ORDER BY UPPER(' + sortCol + ') ' + sortDir;
offset = ' OFFSET :start_row ROWS FETCH NEXT :num_rows ROWS ONLY';
query += orderBy;
query += offset;
logger.info("Begin: " + (new Date().toString()));
async.parallel({
rows: function (callback) {
pool.getConnection(function (err, connection) {
logger.info("Begin Connection: " + (new Date().toString()));
if (err) {
logger.error(err.message);
return;
}
logger.info("Begin execute: " + (new Date().toString()));
connection.execute(
query,
{
start_row: startRow,
num_rows: numRows
},
function (err, result) {
logger.info("End execute: " + (new Date().toString()));
if (err) {
logger.error(err.message);
callback("Something broke in the first thing");
doRelease(connection);
return;
}
console.log(result.rows);
var procJson = [];
/**
* For each row in the result, pushes a new object to the rows array
* In each new object, the key is assigned and the result row value set
*/
for (var i = 0; i < result.rows.length; i++) {
procJson.push({});
for (var j = 0; j < result.metaData.length; j++) {
procJson[i][result.metaData[j].name.toLowerCase()] = result.rows[i][j];
}
}
logger.info("Send JSON: " + (new Date().toString()));
callback(null, procJson);
logger.info("JSON Sent: " + (new Date().toString()));
doRelease(connection);
});
});
},
totalRows: function (callback) {
pool.getConnection(function (err, connection) {
logger.info("Begin Connection: " + (new Date().toString()));
if (err) {
logger.error(err.message);
return;
}
logger.info("Begin execute: " + (new Date().toString()));
connection.execute(
countQuery,
function (err, result) {
logger.info("End execute: " + (new Date().toString()));
if (err) {
logger.error(err.message);
callback("Something broke");
doRelease(connection);
return;
}
logger.info("Send JSON: " + (new Date().toString()));
console.log(result.rows);
callback(null, result.rows[0][0]);
logger.info("JSON Sent: " + (new Date().toString()));
doRelease(connection);
});
});
}
}, function(err, result){
if(err){
logger.error(err);
}
res.send(result);
});
});
Learn more about bind variables here: https://github.com/oracle/node-oracledb/blob/master/doc/api.md#bind
Also, check out the slides from a recent talk I gave. You may get something out of them... https://www.dropbox.com/s/2rhnu74z2y21gsy/Tips%20and%20Tricks%20for%20Getting%20Started%20with%20the%20Oracle%20Database%20Driver%20for%20Node.pdf?dl=0

MySQL, Node.js Sequential actions - How can I do that?

I've the following code:
function query1() {
var defered = Q.defer();
console.log("In query1");
var connection = mysql.createConnection({
host: '........',
user: 'm...c....a.....i',
password: '......Z....9...K',
database: '.....ol'
});
connection.connect(function(err) {
if (!err) {
console.log("Database is connected ...");
} else {
console.log("Error connecting database ...");
}
});
sql = '' +
'select c.ID as CENA_ID, ' +
' c.I_KEY as CENA_NUMERO, ' +
' c.NM_CENA as CENA_NOME, ' +
' b.DS_MAC as MAC_BOX, ' +
' v.DS_CLIENTID as ALEXA_ID, ' +
' v.FK_ID_GRUPO as GRUPO_ID ' +
' from TB_DISPOSITIVOS_VOZ v ' +
' inner join TB_GRUPOS g ' +
' on g.ID = v.FK_ID_GRUPO ' +
' inner join TB_CENAS c ' +
' on g.ID = c.FK_ID_GRUPO ' +
' inner join TB_CENTRAIS b ' +
' on g.ID = b.FK_ID_GRUPO ' +
'where v.DS_CLIENTID = "' + userId + '" ' +
'and lower(c.NM_CENA) like "%' + sceneName.toLowerCase() + '%"';
console.log("Created query");
try{
connection.query(sql, function(erro, rows, fields) {
if (!erro) {
console.log("Executed query verifying the userId");
contador = 0;
if (rows.length > 0) {
cena_id = rows[0].CENA_ID;
cena_numero = rows[0].CENA_NUMERO;
cena_nome = rows[0].CENA_NOME;
alexa_id = rows[0].ALEXA_ID;
grupo_id = rows[0].GRUPO_ID;
mac_box = rows[0].MAC_BOX;
contador = contador + 1;
}
console.log("contador: " + contador);
} else {
console.log("Error - getting the Alexa register in database" + erro);
context.fail("Error - getting the Alexa register in database" + erro);
}
});
}catch (ex){
console.log("exception: " + ex);
}
}
And this code as well:
Q.all([query1()]).then(function(results) {
console.log("Q.all log function");
if (contador > 0) {
console.log("contador > 0");
var client = mqtt.connect('mqtt://.............com');
console.log("connected to MQTT broker");
var buffer = [26,
0,0,0,0,555,645,0,0,0,0,0,
0,5555,2,Math.floor((Math.random() * 200) + 1),
0,0,0,333,13,4,0,1,0,
cena_numero
];
console.log("Created buffer");
client.on('connect', function() {
client.publish('n/c/' + mac_box + '/app', buffer);
console.log("sent MQTT");
});
speechOutput = "Command " + sceneName + " executed successfully";
repromptText = "";
console.log("Process executed successfully")
} else {
console.log("contador <= 0");
speechOutput = "This command was not found!";
repromptText = "";
}
}, function (reason) {
console.log("reason: " + reason);
});
How can I do for the second code execute only if the first query1() executed correctly? Because in the function query1() i've a MySQL Query, and I only can continue with the process after the result of this query.
Anyone can help me?
Thanks a lot!
You're missing some key concepts regarding callbacks and asynchronous behavior in Node.js. You're using the "Q" library (btw I'd recommend trying bluebird instead) to handle promises, but your "query1" function does not return a promise. That's why query1 executes but your "Q.all log function" will execute before query1 is finished.
You can structure your code like this instead (I'll give an example with bluebird since I'm more familiar with it):
var Promise = require('bluebird');
var _connection;
function query1() {
return new Promise(resolve, reject) {
//open your connection
connection.open(function (err, connection) {
if (err) return reject(err);
_connection = connection;
//do your query
_connection.query(sql, [params], function (err, data) {
if (err) return reject(err);
else resolve(data);
});
});
});
}
function query2(data) {
return new Promise(resolve, reject) {
//do your query, using data passed in from query1
_connection.query(sql, [params], function (err, data) {
if (err) return reject(err);
else resolve(data);
});
});
}
query1
.then(function (data) { query2(data); })
.catch(function (err) {
console.log('error:', err);
});
Also, just FYI, concatenating SQL string like this is a no-no that will open you up to a SQL injection attack:
like "%' + sceneName.toLowerCase() + '%"
Instead, use like "%?%" and call your SQL with connection.query(sql, [sceneName], function(err, data) {}). Hope this helps.
I solved my problem with asyncpackage like this:
var async = require('async');
async.series([
function(callback) {
//action 1...
},
function(callback){
//action 2...
}
], function(err) {
if (err) {
speechOutput = "Scene not found!";
repromptText = "Please try again.";
}
console.log("Before speechOutput");
callback(sessionAttributes,
buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
});

Retrieving a value from a node child process

var fp = 'ffprobe ' + fileName + ' -show_streams | grep '
var width = exec(fp+'width', function(err, stdout, stderr){
return stdout;
});
alert(stdout + 'random example');
how do I get the stdout 'out' of the process so that I can use it later.
Node's exec function is asynchronous. This means that there is no guarantee that code below the exec call will wait until the child process finishes to run. To execute code once the process quits, then, you must provide a callback which deals with the results. Your code can branch off from there:
var fp = 'ffprobe ' + fileName + ' -show_streams | grep ';
var width = exec(fp+'width', function(err, stdout, stderr){
console.log(stdout);
// ... process stdout a bit ...
afterFFProbe(stdout);
});
function afterFFProbe(output) {
// your program continues here
}
None of the answers above worked for me. This did though.
var probeCommand = 'rtsp://xx.xx.xx.xx/axis-media/media.3gp'
exec('ffprobe '+probeCommand+' | echo ',function(err,stdout,stderr){
console.log(stdout+stderr)
})
If I'm understanding you correctly:
var fp = 'ffprobe ' + fileName + ' -show_streams | grep ',
value,
width = exec(fp+'width', function(err, stdout, stderr) {
value = stdout;
return stdout;
});
alert(value + 'random example');
I think this might work:
var output = "";
var fp = 'ffprobe ' + fileName + ' -show_streams | grep '
var width = exec(fp+'width', function(err, stdout, stderr){
this.output = stdout;
});
alert(output + 'random example');

Categories

Resources