Release PostgeSQL connection Pool in Nodejs - javascript

I am trying to connect my application to the database using the connection pool method, its connecting fine, and data insertion is happening fine without any issues but other queries in the same file are slowing down.
I have tried with release() method also not working properly.
How can release the pool to the next query once it's executed the current query?
Below is my dbpool.js file code where I am writing a common generalized database connection,
var pg = require('pg');
var PGUSER = 'postgres';
var PGDATABASE = 'test_database';
var config = {
user: PGUSER, // name of the user account
host: 'localhost',
database: PGDATABASE, // name of the database
password: 'password#AWS',
port: 5432,
max: 10,
idleTimeoutMillis: 10000
};
const pool = new pg.Pool(config);
const DB = {
query: function(query, callback) {
pool.connect((err, client, done) => {
if(err){ return callback(err); }
client.query(query, (err, results) => {
// done();
client.release();
// if(err) { console.error("ERROR: ", err) }
if(err) { return callback(err); }
callback(null, results.rows);
})
});
}
};
module.exports = DB;
I tried with both the done() and client.release() method but no luck. If I use both then I am getting an error message client is already released.
Below is my socket.js file code:
var express = require('express');
const connection = require('./dbpool.js');
if(arData == '0022'){
const queryText = "INSERT INTO alert(alert_data) VALUES('"+arData+"')";
connection.query(queryText,(err, res) => {
if(err){
console.log(err.stack);
}
});
}
if(arData == '0011'){
const queryText = "INSERT INTO table2(alert_data) VALUES('"+arData+"')";
connection.query(queryText,(err, res) => {
if(err){
console.log(err.stack);
}
});
}
function ReverseCommunication(){
const select1 = "SELECT * FROM alert WHERE action = '0' ORDER BY alert_id ASC LIMIT 1";
connection.query(select1, (err, res) =>{
if(err) {
console.log("Error1");
res.json({"error":true});
}
else{
console.log("res==",res);
}
});
}
setInterval(function(){
ReverseCommunication();
}, 2000)

With pool you shouldn't need to close the connection. With pool it will reuse the connection pool for subsequent request so you don't have to connect to the DB each time.
(i'm not a PG expert here, sure other could expand on that way better then I )
What works for us is to set up the dbpool file you have like this
const {Pool,Client} = require('pg');
const pool = new Pool({
user: process.env.POSTGRES_USER,
host: process.env.POSTGRES_URL,
database: process.env.POSTGRES_DATABASE,
password: process.env.POSTGRES_PASSWORD,
port: process.env.POSTGRES_PORT,
keepAlive: true,
connectionTimeoutMillis: 10000, // 10 seconds
max: 10
});
pool.connect()
.then(() => console.log('pg connected'))
.catch(err => console.error(err))
module.exports = pool
Then use the pool.query like you have now with pool.connect
Also, just a side note what lib are you using for PG? Noticed your queries are dynamic, you may want to adjust those to prevent possible SQL-injection.

Related

MySQL Can not open connection after call connection.end() => Error: Pool is closed

config.js
const mysql = require('mysql2');
const config = {
host: 'localhost',
port: '3306',
user: 'root',
password: 'root',
database: 'krometal',
charset: "utf8mb4_bin",
multipleStatements: true
};
const connection = mysql.createPool(config);
connection.getConnection(function (err, connection) {
//connecting to database
if (err) {
logger.log('error', err);
console.log("MYSQL CONNECT ERROR: " + err);
} else {
logger.log('info', "MYSQL CONNECTED SUCCESSFULLY.");
console.log("MYSQL CONNECTED SUCCESSFULLY.");
}
});
module.exports = {
connection
}
login.js
const loginUser = async (req, callback) => {
connection.query(sql, async function (err, rows) => {
// logic
callback(result, 401, connection);
})
}
route.js
users.post('/users/login', async (req, res) => {
await loginUser(req, async (response, code, connection) => {
await connection.end();
res.status(code).send(response);
});
});
The problem is the first time I try login worked fine, but if I try the same login API again throw the error Error: Pool is closed.
Should I use the
connection.end()
method every time I open connection or mysql2 automatically end connection?
Don't run
await connection.end();
After running this function you need to create a new connection using
connection.getConnection();

Connecting to mySql with node, error: code: 'PROTOCOL_ENQUEUE_HANDSHAKE_TWICE', fatal: false

I am making a sign up page and am using express to communicate.
As such, I have an express.js file that when it gets a post it will run a function on my mysql.js file.
Express.js:
//Defining node js libraries
import Express from "express"
import cors from "cors"
import bodyParser from "body-parser"
const app = Express()
const port = 3000
//Import sql connection function
import { run_db } from "./mysql.js"
// We are using our packages here
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true}));
app.use(cors())
//Route that handles login logic
app.post('/login', (req, res) =>{
const json_db_value = {
"email": req.body.email.toString(),
"password": req.body.password.toString(),
"username": req.body.username.toString()
}
run_db(json_db_value)
})
//Start your server on a specified port
app.listen(port, ()=>{
console.log(`Server is running on port ${port}`)
})
And here is my mysql.js file
//Import mySql library
import mysql from "mysql"
//Runs sql code through db
export let run_db = (insert_values) => {
//Create connection to database
const db_connect = mysql.createConnection({
host: "localhost",
user: "root",
password: "*******",
database: "store_user_info"
})
//Sql code to execute
const sql_code =
`INSERT INTO Users (email,password,username)
VALUES (
${"'"+insert_values.email+"'"},
${"'"+insert_values.password+"'"},
${"'"+insert_values.username+"'"}
)`
//Run sql code and fetch result
db_connect.connect((err) => {
if (err) throw err
db_connect.query("SELECT * FROM Users",(err,result) => {
if (err) throw err
for (let i=0;i<Object.keys(result).length;i++) {
if (result[i].email===insert_values.email || result[i].username===insert_values.username) {
console.log("email/username is taken")
return
}else {
console.log("email/username is avaliable")
insert_values_to_db()
return
}
}
})
})
let insert_values_to_db = () => {
db_connect.connect((err) => {
if (err) throw err
db_connect.query(sql_code,(err,result) => {
if (err) throw err
})
})
}
}
For the first connect, I make sure the email and username are still avaliable, and then i runs the sql code to insert them into the database. I'm pretty sure that is what's causing the error, but is there another way to run 2 sql connects on the same db?
Try using mysql2 which should be api compatible. Then do mysql.createPool instead of createConnection.
Also your code is incorrect. You shouldn't do db_connect.connect multiple times. That's where your error is coming from. You should only connect once (but you should probably use a pool because they are better and don't timeout and stuff).
So you should do this:
//Import mySql library
import mysql from "mysql2"
//Runs sql code through db
export let run_db = (insert_values) => {
//Create connection to database
const db_connect = mysql.createPool({
host: "localhost",
user: "root",
password: "*******",
database: "store_user_info"
})
//Sql code to execute
const sql_code =
`INSERT INTO Users (email,password,username)
VALUES (
${"'"+insert_values.email+"'"},
${"'"+insert_values.password+"'"},
${"'"+insert_values.username+"'"}
)`
//Run sql code and fetch result
let insert_values_to_db = () => {
if (err) throw err
db_connect.query(sql_code,(err,result) => {
if (err) throw err
})
}
if (err) throw err
db_connect.query("SELECT * FROM Users",(err,result) => {
if (err) throw err
for (let i=0;i<Object.keys(result).length;i++) {
if (result[i].email===insert_values.email || result[i].username===insert_values.username) {
console.log("email/username is taken")
return
}else {
console.log("email/username is avaliable")
insert_values_to_db()
return
}
}
})
}

Mysql node.js intermittent connectivity issue

In my node.js app I am using the mysql library for database connectivity.
When I start my node server I can query the database perfectly fine – no issues
When I query the database after 5 minutes the server returns the following error:
{"code":"PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR","fatal":false}
If I restart my node.js server I can query again with no issues…
Here is my code
const mysql = require('mysql');
let connection = mysql.createPool({
host: config.mysql.host,
user: config.mysql.user,
password: config.mysql.password,
database: config.mysql.database
});
router.post('/subscription', (req, res) => {
const user = req.body;
const q = 'INSERT into Subscription SET ?';
connection.query(q, user, (err, results) => {
if (err)
return res.json(err);
return res.json(results);
});
});
I have used both mysql.createConnection and mysql.createPool…. also tried ending the connection manually with connection.end….
Both results end in the same error.
You need to get a connection from the pool and use that, not query the pool itself. When you get a connection from the pool, the pool will make sure you get a valid connection from the pool. So your code would be:
const mysql = require('mysql');
let pool = mysql.createPool({
host: config.mysql.host,
user: config.mysql.user,
password: config.mysql.password,
database: config.mysql.database
});
router.post('/subscription', (req, res) => {
const user = req.body;
const q = 'INSERT into Subscription SET ?';
pool.getConnection(function(err, connection) {
if (err)
return res.json(err);
connection.query(q, user, (err, results) => {
if (err)
return res.json(err);
return res.json(results);
});
})
});
UPDATE:
You don't need to do separate pool.getConnection and connection.query, you can combine them into a pool.query which will get a connection, do the query and release the connection. So, the updated code would be:
const mysql = require('mysql');
let pool = mysql.createPool({
host: config.mysql.host,
user: config.mysql.user,
password: config.mysql.password,
database: config.mysql.database
});
router.post('/subscription', (req, res) => {
const user = req.body;
const q = 'INSERT into Subscription SET ?';
pool.query(q, user, function(err, connection) {
if (err)
return res.json(err);
return res.json(results);
});
});

How to get data from response of Mysql connection

I want to know whether there is any existing user with emailid in my db by the name say xyz#abc.com .
function isDuplicateUser(emailId)
{
var sql='SELECT count(*) FROM UserDetails WHERE emailId ="'+emailId+'";';
var con = mysql.createConnection({
host:"localhost",
user: "root",
password: "32577488",
database:"mydb"
});
con.connect(function(err) {
con.query(sql, function (err, result) {
if (err) throw err;
console.log("Inside Duplicate check");
console.log(result[0]);
console.log(result.count);
console.log(result[0].emailId);
console.log(result[0].count);
console.log("1 record inserted");
});
});
}
But in all the console.log statements I am getting undefined ! I thought of using count so that if there is more than 0 than there exists a user with that userid ! Please help me ! I have another doubt also It is ok to get connection in every function ! Like for signup have a
function signup(email,password,name)
{
var sql =''....;
//getting connection once
}
function signin(emailid,password)
{
//getting connection here
return success;
}
It seems like code is getting replicated many times !
please, try with this sql statement and let me know the result:
// replace your var sql with this one
const sql = `SELECT count(*) FROM UserDetails WHERE emailId = '${emailId}'`;
In the other hand, regarding how to manage connection in each function, my recommendation is create a pool of connections in your app and get a connection from the pool on each function you need (you need to take care about releasing the connection when you finish to make them available for new incoming requests):
// connection first time when node starts
const options = {
connectionLimit: 10,
host: HOST,
user: USER,
password: PASSWORD,
database: DATABASE,
port: 3306,
timezone: 'Z',
// debug: true,
multipleStatements: true,
// ...azureCertificate && sslOptions,
};
const pool = mysql.createPool(options);
// on each function, get a connection from the pool using this function
getConnection() {
return new Promise((resolve, reject) => {
if (pool === null) {
return reject(new Error(`MySQL connection didn't established. You must connect first.`));
}
pool.getConnection((err, connection) => {
if (err) {
if (connection) {
connection.release();
}
return reject(err);
}
return resolve(connection);
});
});
}
Hope this helps.
This example was made using npm package mysql: https://www.npmjs.com/package/mysql

How to use another MongoDB database using Node.js [duplicate]

How do I connect to mongodb with node.js?
I have the node-mongodb-native driver.
There's apparently 0 documentation.
Is it something like this?
var mongo = require('mongodb/lib/mongodb');
var Db= new mongo.Db( dbname, new mongo.Server( 'mongolab.com', 27017, {}), {});
Where do I put the username and the password?
Also how do I insert something?
Thanks.
Per the source:
After connecting:
Db.authenticate(user, password, function(err, res) {
// callback
});
Everyone should use this source link:
http://mongodb.github.com/node-mongodb-native/contents.html
Answer to the question:
var Db = require('mongodb').Db,
MongoClient = require('mongodb').MongoClient,
Server = require('mongodb').Server,
ReplSetServers = require('mongodb').ReplSetServers,
ObjectID = require('mongodb').ObjectID,
Binary = require('mongodb').Binary,
GridStore = require('mongodb').GridStore,
Code = require('mongodb').Code,
BSON = require('mongodb').pure().BSON,
assert = require('assert');
var db = new Db('integration_tests', new Server("127.0.0.1", 27017,
{auto_reconnect: false, poolSize: 4}), {w:0, native_parser: false});
// Establish connection to db
db.open(function(err, db) {
assert.equal(null, err);
// Add a user to the database
db.addUser('user', 'name', function(err, result) {
assert.equal(null, err);
// Authenticate
db.authenticate('user', 'name', function(err, result) {
assert.equal(true, result);
db.close();
});
});
});
var mongo = require('mongodb');
var MongoClient = mongo.MongoClient;
MongoClient.connect('mongodb://'+DATABASEUSERNAME+':'+DATABASEPASSWORD+'#'+DATABASEHOST+':'DATABASEPORT+'/'+DATABASENAME,function(err, db){
if(err)
console.log(err);
else
{
console.log('Mongo Conn....');
}
});
//for local server
//in local server DBPASSWOAD and DBusername not required
MongoClient.connect('mongodb://'+DATABASEHOST+':'+DATABASEPORT+'/'+DATABASENAME,function(err, db){
if(err)
console.log(err);
else
{
console.log('Mongo Conn....');
}
});
I find using a Mongo url handy. I store the URL in an environment variable and use that to configure servers whilst the development version uses a default url with no password.
The URL has the form:
export MONGODB_DATABASE_URL=mongodb://USERNAME:PASSWORD#DBHOST:DBPORT/DBNAME
Code to connect this way:
var DATABASE_URL = process.env.MONGODB_DATABASE_URL || mongodb.DEFAULT_URL;
mongo_connect(DATABASE_URL, mongodb_server_options,
function(err, db) {
if(db && !err) {
console.log("connected to mongodb" + " " + lobby_db);
}
else if(err) {
console.log("NOT connected to mongodb " + err + " " + lobby_db);
}
});
My version:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://user:pass#dhost:port/baseName', function(err, db) {
if (err) {
console.error(err);
}
var collection = db.collection('collectionName');
collection.find().toArray(function(err, docs) {
console.log(docs);
});
});
I recommend mongoskin I just created.
var mongo = require('mongoskin');
var db = mongo.db('admin:pass#localhost/mydb?auto_reconnnect');
db.collection('mycollection').find().toArray(function(err, items){
// do something with items
});
Is mongoskin sync? Nop, it is async.
Here is new may to authenticate from "admin" and then switch to your desired DB for further operations:
var MongoClient = require('mongodb').MongoClient;
var Db = require('mongodb').Db, Server = require('mongodb').Server ,
assert = require('assert');
var user = 'user';
var password = 'password';
MongoClient.connect('mongodb://'+user+':'+password+'#localhost:27017/opsdb',{native_parser:true, authSource:'admin'}, function(err,db){
if(err){
console.log("Auth Failed");
return;
}
console.log("Connected");
db.collection("cols").find({loc:{ $eq: null } }, function(err, docs) {
docs.each(function(err, doc) {
if(doc) {
console.log(doc['_id']);
}
});
});
db.close();
});
This worked for me:
Db.admin().authenticate(user, password, function() {} );
You can do it like this
var db = require('mongo-lite').connect('mongodb://localhost/test')
more details ...
if you continue to have problems with the native driver, you can also check out sleepy mongoose. It's a python REST server that you can simply access with node request to get to your Mongo instance.
http://www.snailinaturtleneck.com/blog/2010/02/22/sleepy-mongoose-a-mongodb-rest-interface/
With the link provided by #mattdlockyer as reference, this worked for me:
var mongo = require('mongodb');
var server = new mongo.Server(host, port, options);
db = new mongo.Db(mydb, server, {fsync:true});
db.open(function(err, db) {
if(!err) {
console.log("Connected to database");
db.authenticate(user, password, function(err, res) {
if(!err) {
console.log("Authenticated");
} else {
console.log("Error in authentication.");
console.log(err);
}
});
} else {
console.log("Error in open().");
console.log(err);
};
});
exports.testMongo = function(req, res){
db.collection( mycollection, function(err, collection) {
collection.find().toArray(function(err, items) {
res.send(items);
});
});
};
Slight typo with Chris' answer.
Db.authenticate(user, password, function({ // callback }));
should be
Db.authenticate(user, password, function(){ // callback } );
Also depending on your mongodb configuration, you may need to connect to admin and auth there first before going to a different database. This will be the case if you don't add a user to the database you're trying to access. Then you can auth via admin and then switch db and then read or write at will.
const { MongoClient } = require('mongodb');
// or as an es module:
// import { MongoClient } from 'mongodb'
// Connection URL
const url = 'mongodb://localhost:27017';
const client = new MongoClient(url);
// Database Name
const dbName = 'myProject';
async function main() {
// Use connect method to connect to the server
await client.connect();
console.log('Connected successfully to server');
const db = client.db(dbName);
const collection = db.collection('documents');
// the following code examples can be pasted here...
return 'done.';
}
main()
//what to do next
.then(console.log)
//if there is an error
.catch(console.error)
// what to do in the end(function result won't matter here, it will execute always).
.finally(() => client.close());
you can find more in the documentation here: https://mongodb.github.io/node-mongodb-native/4.1/
I'm using Mongoose to connect to mongodb.
Install mongoose npm using following command
npm install mongoose
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/database_name', function(err){
if(err){
console.log('database not connected');
}
});
var Schema = mongoose.Schema;
var userschema = new Schema ({});
var user = mongoose.model('collection_name', userschema);
we can use the queries like this
user.find({},function(err,data){
if(err){
console.log(err);
}
console.log(data);
});

Categories

Resources