Mysql node.js intermittent connectivity issue - javascript

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);
});
});

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();

Release PostgeSQL connection Pool in Nodejs

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.

`Cannot set headers after they are sent to client` error when using mysql2 async/await

I am changing my backend (switching over from Mongo to MySql). I know the error is getting thrown because a return statement is being executed before my SQL query has finished and then when my sql query finishes, it tires to send another res.send, hence why I am trying to use mysql2 with Promise wrappers to use await on queries in my async function.
I have a separate file that creates the DB connection so I can access the connection throughout my Nodejs backend:
const mysql = require('mysql2');
async function pool(){
const pool = await mysql.createPool({
host: "ip",
user: "username",
password: "password",
database: "db"
});
return pool
}
exports.getConnection = async function(callback) {
const currentPool = await pool();
currentPool.getConnection(function(err, conn) {
if(err) return callback(err);
callback(err,conn)
});
};
Then, to create a query that follows async/await:
sql.getConnection(async function(err, client){
client.query(`select email from users where email = "${email}"`, function (error, result){
if(error) return res.status(500).send('an internal db error occurred');
// carry on with code ...
});
});
I've tried using await on the query too:
await sql.getConnection(async function(err, client){
client.query(`select email from users where email = "${email}"`, function (error, result){
if(error) return res.status(500).send('an internal db error occurred');
// carry on with code ...
});
});
What am I missing? I haven't tired to use the normal mysql NPM library and make my own promise wrapper yet...
NEW CODE:
I've updated my function:
const mysql = require('mysql2');
const pool = mysql.createPool({
host: "ip",
user: "user",
password: "pass",
database: "db"
});
exports.db = (sql) => {
new Promise((resolve, reject) => {
pool.getConnection((err, conn) => {
if(err) return reject(err);
conn.query(sql, (err, results, fields) => {
conn.release()
if(err) return reject(err)
console.log(results)
resolve(results);
});
});
});
}
Then I call it via:
try{
const emailExisit = await sql.db(`SELECT email FROM users WHERE email = "${email}"`);
console.log(emailExisit);
if(emailExisit.length > 0) return res.status(422).send({"data": "", "code": "105", "message": "An account with given email already exists"});
}catch (err) {
console.log(err)
return res.status(500).send({"data": "", "code": "108", "message": `There seems to be an error contacting the database. Try again later <br> ${err}`});
}
However, my code still continues, leaving my emailExists variable undefined (yes, it is inside an async function)
This is my configuration to use MySQL with Node.js. I hope it works with you.
/config/mysql.js
const mysql = require('mysql2');
const pool = mysql.createPool({
host: process.env.MYSQL_HOST,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
port: process.env.MYSQL_PORT,
database: process.env.MYSQL_DB_NAME,
});
const query = (query, args = []) =>
new Promise((resolve, reject) => {
pool.getConnection((err, connection) => {
if (err) {
return reject(err);
}
connection.query(query, args, (err, results) => {
connection.release();
if (err) {
return reject(err);
}
resolve(results);
});
});
});
module.exports = { query };
/index.js
const { query } = require('./mysql');
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.get('/api/v1/sum', (req, res) => {
query('SELECT 1 + 1 as sum')
.then(results => {
res.json({ sum: results[0].sum });
})
.catch(err => {
console.error(err);
res.status(500).json({ error: 'error msg' });
});
});
// anther example with async
app.get('/api/v1/sum', async (req, res) => {
try {
const results = await query('SELECT 1 + 1 as sum');
res.json({ sum: results[0].sum });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'error msg' });
}
});
app.listen(3000);

Post isn't sending data do mySql table

I'm new at programming and I've been trying to make a post that allows me to send data from an ancount form into a table( mysql database). However the console.log(on the node node console shows me an error) and I can't seem to understand why the post isn't working.
I get the error cannot enqueue Handshake after already enqueuing a Handshake, even though I've googled about, I haven't found a way to make the post work or get rid of this error.
Appreciate for any help.
const express = require('express');
const mysql = require('mysql');
// Create connection
const db = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '',
database : 'nodemysql'
});
// Connect
db.connect((err) => {
if(err){
throw err;
}
console.log('MySql Connected...');
});
const app = express();
app.get('/', function (req, res) {//nome da minha url req(é o que vai na url/ res é o response é o ficheiro)
res.sendFile(path.join(__dirname+'/public/index.html'));
})
app.get('/log_in', function (req, res) {//nome da minha url
res.sendFile(path.join(__dirname+'/public/signin.html'));
})
app.get('/register', function (req, res) {//nome da minha url
res.sendFile(path.join(__dirname+'/public/register.html'));
})
// Create DB
app.get('/createdb', (req, res) => {
let sql = 'CREATE DATABASE IF NOT EXISTS nodemysql';
db.query(sql, (err, result) => {
if(err) throw err;
console.log(result);
res.send('Database created...');
});
});
// Create table
app.get('/createusertable', (req, res) => {
let sql = 'CREATE TABLE user (id int AUTO_INCREMENT, name VARCHAR(50), last_name VARCHAR(50),email VARCHAR(100),password VARCHAR (100),phone VARCHAR (50),country VARCHAR(100),vat_number VARCHAR(9),address VARCHAR(150), PRIMARY KEY(id))';
db.query(sql, (err, result) => {
if(err) throw err;
console.log(result);
res.send('Post table created...');
});
});
db.connect(function(err){
if(err) return console.log(err);
console.log('conectou!');
createTable(connection);
})
app.listen('3000', () => {
console.log('Server started on port 3000');
});
app.use(express.static('public'))
const bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
app.post('/register', function (req, res) {
console.log(req.body.user.name);
let post = {name:req.body.user.name, last_name:req.body.user.lastName,
email:req.body.user.email, password:req.body.user.password, phone:req.body.user.phone,
country:req.body.user.country, vat_number:req.body.user.nif, address:req.body.user.address};
let sql = 'INSERT INTO user SET ?';
let query = db.query(sql, post, (err, result) => {
if(err) throw err;
res.redirect(303,'/');
});
});
It looks like you initiate another db.connect in your create table step after you already initiated a connect in the beginning of your script.
This is a double connection initiation, without any connection.end(); to close the initially opened connection.
I think you will have more luck when you remove the db.connect from your "create table" step.
Please view this documentation to further clarify my point.

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

Categories

Resources