how much connection.release() must have in node js code? - javascript

I am using node js for web service I use pool.getConnection() in my code , after use pool.getConnection() for close this connection i am using connection.release(); but in any query i am not use any function for close connection .please tell me this code is valid or not?.
pool.getConnection(function(err,connection){
connection.release();
if(!err){
email=req.user.email
connection.query('select * from users where email=?',[email],
function(err,user_detail){
if(!err)
{
connection.query('insert into message(??,time,type,user_id) values(?,?,?,?)',[messagecolumns,dbValues,time,type,user_id],
function(err,message_inserted){
if(!err)
{
console.log('Message send',message_inserted.insertId);
connection.query('select u.firstname,u.lastname,u.img_path,m.* from users u, message m where u.id=m.user_id and m.id=?',[message_inserted.insertId],
function(err,message_detail){
if(!err)
{
connection.query('select count(id) as message_count from message where appointment_request_id=?',[appointment_request_id],
function(err,total_message){
if(!err)
{
connection.query('update appointment_request set message_count=? where appointment_request_id=?',[total_message[0].message_count,appointment_request_id],
function(err,update_message_count){
if(!err)
{
}
});
}
else {
console.log('connection Error',err);
}
I feel this is not valid method for connection because from some web site I realize that after SQL query I must close connection but in this code I never use any close connection and my code are some time give me 500 server error and some time it work successfully so I have to fix this error and I want to permanently solution if anyone can help me please give me solution for this. if you have any confutation for understanding you may ask me.

A pool has a limited number of connections (Default is 10).
When you getConnection then one of those connections is removed from pool and is passed to you so that you can use it. You will call connection.release() after you are finished working with the connection. As soon as you called connection.release() the connection is passed back to the pool and is free to be used by other parts of your code. As of that it is not valid to work with this connection after you have called release on it, because it might be closed or used by another part of your code that requested a connection with getConnection (in most of the cases it might still work, but it could unexpectedly fail).
In your code you call connection.release(); at the beginning of you callback so the usage of connection after that release is not valid.
You you must not call connection.release() multiple times on the same connection.

Related

Calling node-oracledb's createPool Method

I am creating a RESTful API that uses Node.js and Express. My application uses an Oracle database so I installed the node-oracledb module from npm. I've looked through the documentation and viewed some of the samples presented in the module's github page; however, I don't see any examples where a connection pool is used. Correct me if I'm wrong, but for applications that will make many calls to the database the recommendation is to use connection pools as opposed to using standalone connections. Below is a sample of the code I wrote:
createPool = function(poolAttrs, fetchPool){
oracledb.createPool(poolAttrs, function(error, pool){
if(error){
console.error(`Could not create pool using specified attributes: `, error.message);
}
else{
console.log(`Pool created successfully using poolAlias: ${poolAttrs.poolAlias}`);
fetchPool(pool);
}
});
};
createConnection = function(poolAlias, connection){
oracledb.getConnection(poolAlias, function(error, conn){
if(error){
console.error(`Could not get connection: `, error.message);
} else {
console.log(`New connection obtained: ${conn}`);
connection(conn);
}
});
};
executeQuery = function(queryString, poolAlias){
console.log(queryString);
var conn = createConnection(poolAlias, function connection(conn){
conn.execute(queryString, function(error, result){
if(error){
console.error(`Could not execute query: `, error.message);
} else {
console.log(result);
}
conn.close(function(error){
if(error){
console.error(`Could not close connection.`);
} else {
console.log(`Connection successfully closed.`);
}
})
});
});
}
closePool = function(pool){
pool.close(60, function(error){
if(error){
console.error(`Could not close connection pool ${pool.poolAlias}`, error.message);
} else {
console.log(`Pool closed successfully.`);
}
});
};
createPool(attrs, function fetchPool(pool){
var poolAlias = pool.poolAlias;
console.log(poolAlias);
});
executeQuery(queryString, attrs.poolAlias);
When I run this code I get the following error:
Could not get connection: NJS-047: poolAlias "amDBpool" not found in the connection pool cache
I know why the error is happening. As my understanding of callbacks go, I know that calling the asynchronous createPool() function with the fetchPool(pool) callback registers this callback (fetchPool) in the callback stack. All synchronous code will execute before it. So when I call executeQuery and the function reaches the line of execution where it calls createConnection(poolAlias...) the poolAlias variable is null since the createPool function is still waiting in the callback stack to execute. Hence, no pool with the alias "poolAlias" exists and the call fails. I know that I could stick the call to createPool inside the executeQuery method, but wouldn't that try to create a new pool every time I execute a query? My question is, is there a way to test inside the executeQuery method that the pool exists, and if it does then not try to recreate it. Other than this, the only other way to do this would be with an Promises or Async/Await right?
The node-oracledb examples using a connection pool are the connectionpool.js and examples/webap.js files. Yes, a connection pool would be a good idea in a web service. Also I recommend using the async/await style of programming.
You can see the examples creates a connection pool before doing anything else:
await oracledb.createPool({
user: dbConfig.user,
password: dbConfig.password,
connectString: dbConfig.connectString
});
The returned pool from the oracledb.createPool() call is ignored because the pool is later accessed via the pool cache since no credentials are passed to getConnection():
let connection = await oracledb.getConnection();
This uses the default pool alias (which happens to be the string "default"), so no alias is specified when the pool is created or used.
Documentation and tips on using node-oracledb connection pools is in Connection Pooling.
You may be interested in Creating a REST API with Node.js and Oracle Database,
A node-oracledb Web Service in Docker and Demo: GraphQL with Oracle Database and node-oracledb

how can make mongoose fail when executing find query

Hi everyone I'm writing mocha unit tests for my server. How can I get error for mongoose find query. I've tried close the connection before execute but there's nothing firing.
User.find({}, (err, result) => {
if (err) {
// I want to get here
}
return done(result);
});
The following DO NOT WORK with mongoose, at least for now (5.0.17) :
Closing the connection to mongoose is a way to test it, in addition to a proper timeout to set on the find request.
const request = User.find({});
request.maxTime(1000);
request.exec()
.then(...)
.catch(...);
or
User.find({}, { maxTimeMS: 1000 }, (err, result) => {
if (err) {
// I want to get here
}
return done(result);
});
EDIT after further researches :
After trying it myself, it seems that I never get an error from the request.
Changing request maxTime or connection parameters auto_reconnect, socketTimeoutMS, and connectTimeoutMS do not seems to have any effect. The request still hang.
I've found this stack overflow answer saying that all request are queued when mongoose is disconnected from the database. So we won't get any timeout from there.
A soluce I can recommand and that I use on my own project for another reason would be to wrap the mongoose request into a class of my own. So I could check and throw an error myself in case of disconnected database.
In my opinion, the best way to test your error handling is to use mock. More information in this previous stackoverflow topic.
You can mock the mongoose connection and api to drive your test (raise errors...).
Libraries:
sinonjs
testdouble
I solved it like below. Here is the solution.
User = sinon.stub(User.prototype, 'find');
User.yields(new Error('An error occured'), undefined);
By this code it will return error. #ormaz #grégory-neut Thanks for the help.

NodeJS one-shot script using MongoDB connection pooling - how to terminate?

I'm aware of the best practice of MongoDB connection pooling in NodeJS of the singleton DB connection type like this
var db = null;
var connection = function getDBConnection(callback) {
if(db) { callback(null, db) } else { MongoClient.connect( .... ) }
}
module.exports = getDBConnection;
However, what I cannot get my head around at the moment is how to handle this in a one-shot script that, say, does some pre-initialization on the documents of a certain db collection:
getDBConnection(function (err, database) {
var collection = database.collection("objects");
var allObjectsArray = collection.find( /* ... */
).toArray(function (err, objects) {
if(err != null) console.log(err);
assert.equal(null, err);
_.each(objects, function (item) {
collection.update(
{ id: item.id},
{ $set: { /* ... */ }},
function (err, result) {
if(err != null) console.log(err);
assert.equal(null, err);
}
);
});
// database.close(); <-- this fails with "MongoError: Connection Closed By Application", thrown by the update callback
});
// database.close(); <-- this fails too, thrown by the toArray callback
});
If I call the script like that, it never terminates, due to the still open connection. If I close the connection at the bottom, it fails because of, well, a closed connection.
Considering that opening a new connection for every update is not really an option, what am I missing? Keeping the connection open may be fine for webapps, but for a one-shot script called from a shell script this really doesn't work out, does it?
Sorry if this question has arisen before, I've given it some research but have not quite been able to come up with a working answer for me...
Thanks!
Julian
As a "pooled connection" there is code running to keep the connection alive and establish more connections in the pool if required under the driver connection. So much like various "server code" methods, event loop handlers have been invoked and the process does not exit at the end of your code until these are de-registered.
Therefore your two choices to call after all your code has executed are either:
Call db.close() or in your code context specifically database.close() once all is done.
Call process.exit() which is a generic call in node.js applications which will shut the whole process down and therefore stop any other current event loop code. This actually gives you an option to throw an error on exit if you want your code to be "shell integrated" somewhere and look for the exit status.
Or call both. db.close() will allow execution to the next line of code and whatever you put there will also run.
But you have to wait until everything is called, so you can cannot use synchronous loops with asynchronous code in the middle:
async.each(objects,function(item,callback) {
collection.update(
{ "_id": item._id },
{
// updates
},
callback
);
},function(err) {
if (err) throw err;
database.close();
});

simple user login validation module with node

I'm writing my first (non tutorial) node application and am at a point where I'm writing a function that should take the username and password as parameters and query them against the user table of my database to return either true or false. The database is setup, and the app is connecting to it successfully.
However, I haven't worked with SQL very much, nor node, and I'm unsure how to proceed with this function (and short surrounding script). Here it is:
console.log('validator module initialized');
var login = require("./db_connect");
function validate(username, password){
connection.connect();
console.log('Connection with the officeball MySQL database openned...');
connection.query(' //SQL query ', function(err, rows, fields) {
//code to execute
});
connection.end();
console.log('...Connection with the officeball MySQL database closed.');
if(){ //not exactly sure how this should be set up
return true;
}
else{ //not exactly sure how this should be set up
return false;
}
}
exports.validate = validate;
This is using node-mysql. I'm looking for a basic example of how I might set the query and validation up.
I think you'll want to rethink your app into a more node-like way (i.e. one that recognizes that many/most things happen asynchronously, so you're not usually "returning" from a function like this, but doing a callback from it. Not sure what you plan to get from node-mysql, but I would probably just use the plain mysql module. The following code is still most likely not entirely what you want, but will hopefully get you thinking about it correctly.
Note that the use of 'return' below is not actually returning a result (the callback itself should not return anything, and thus its like returning undefined. The return statements are there so you exit the function, which saves a lot of tedious if/else blocks.
Hope this helps, but I'd suggest looking at various node projects on github to get a better feel for the asynchronous nature of writing for node.
function validate(username, password, callback){
var connection = mysql.createConnection({ user:'foo',
password: 'bar',
database: 'test',
host:'127.0.0.1'});
connection.connect(function (err){
if (err) return callback(new Error('Failed to connect'), null);
// if no error, you can do things now.
connection.query('select username,password from usertable where username=?',
username,
function(err,rows,fields) {
// we are done with the connection at this point), so can close it
connection.end();
// here is where you process results
if (err)
return callback(new Error ('Error while performing query'), null);
if (rows.length !== 1)
return callback(new Error ('Failed to find exactly one user'), null);
// test the password you provided against the one in the DB.
// note this is terrible practice - you should not store in the
// passwords in the clear, obviously. You should store a hash,
// but this is trying to get you on the right general path
if (rows[0].password === password) {
// you would probably want a more useful callback result than
// just returning the username, but again - an example
return callback(null, rows[0].username);
} else {
return callback(new Error ('Bad Password'), null);
}
});
});
};

getting TypeError: Cannot call method 'releaseConnection' of null in mysql node.js

i am using mysql felix node.js module.
i am using its pool connection.
i have many queries in my server side (written in node) that are written like this:
this.courtsAmount = function(date, callback){
pool.getConnection(function(err, connection) {
connection.query('SELECT MAX(id) AS result from courts where date="' + date + '"', function(err, rows, fields){
connection.release();
if (err) throw err;
if (rows[0].result)
callback(rows[0].result);
else
callback(0);
});
});
};
for some reason i keep getting this error (from all sorts of functions that are written like this):
Type Error: Cannot call method 'releaseConnection' of null
which is pointing to the 'connection.release()' line.
i really don't understand what is the problem here, as i understand from the API inside the function of pool.getConnection i am supposed to have full access to the connection. maybe it is an issue of something to have to do with timeout of the connection? i believe it is not the case because this error happens while i am actually going through my site.
another question:
do i have to deal with the option that connections will timeout if i use the pool?
and if the answer is yes, how should i do it?
thanks.
I'd recommend adding error checking before attempting to use the connection instance. I've updated your code (see my comments inline):
this.courtsAmount = function(date, callback) {
pool.getConnection(function(err, connection) {
if (err) throw err; // <-- 'connection' might be null, so add an error check here
connection.query('SELECT MAX(id) AS result from courts where date="' + date + '"', function(err, rows, fields) {
if (err) throw err; // <-- moved this line up to check for an error first
connection.release(); // <-- moved this line down so error checking happens first
if (rows[0].result)
callback(rows[0].result);
else
callback(0);
});
});
};
Also, if the date instance is coming from an untrusted source, then your code is vulnerable to SQL injection. You might consider switching to mysql2 and using a prepared statement.

Categories

Resources