Amazon Lex version 2 - Session Timeout exception - aws-sdk

Luego de dos semanas de investigacion y prueba aun no logro encontrar una solucion con AWS.LexRuntimeV2. I create a simple Bot in order to connecto with my nodejs app... If I send the messages quickly using LexRuntimeV2, it will not throw any error, but if it took more than 5 minutes to send a message, after establishing the connection, it throws me an exception:
'The session has been destroyed'
This is my code:
const AWS = require('aws-sdk');
const uniqid = require('uniqid');
const { LexRuntimeV2 } = require('#aws-sdk/client-lex-runtime-v2');
class AmazonLexV2 {
constructor(credentials) {
this.botName = credentials.bot_name;
this.alias = credentials.bot_alias;
this.apiVersion = credentials.apiVersion;
this.region = credentials.region;
this.locale = credentials.locale;
this.lexruntime = new LexRuntimeV2({
apiVersions: credentials.apiVersion,
correctClockSkew: false,
region: credentials.region,
customBackoff: this.retry(),
connectTimeout: 120000 * 10,
timeout: 120000 * 10,
credentials: new AWS.Credentials({
accessKeyId: credentials.access_key_id,
secretAccessKey: credentials.secret_access_key,
expired: false
}),
logger: 'error'
})
}
async sendTextMessageToAWS(textMessage, sessionId) {
return new Promise((resolve, reject) => {
this.lexruntime.recognizeText({
botAliasId: this.alias,
botId: this.botName,
text: textMessage,
localeId: this.locale,
sessionId: (sessionId) ? sessionId : uniqid()
}, (err, response) => {
if (err && err.message === "The session has been destroyed") {
resolve(err.message);
} else if (err) reject(err);
else {
console.log(JSON.stringify(response, undefined, 2));
resolve(response);
}
})
})
}
I dont know how to avoid that session destruction! Could anybody help me?
Thanks

The default Lex session lifetime is 5 minutes. You can change that though.
Please have a look at this guide in the documentation.
Setting Session Timeout

Related

Why I'm always getting an Internal Server Error (code 500) after making a request to BackEnd

I'm having a little trouble with my site and I can't understand what is happening.
First of all I have to say that I was NOT having this behavior when developing on localhost, but now that my site is close to be completed I think that uploading my code to a hosting service and make some tests there would be a good idea.
The issue is that when I make a request to the database, most of the times the site keeps in an eternal loading state, until the error code 500: Internal Server Error appears (I said "most of the times" because it works nice sometime, but normally it remains in a pending state).
Given the fact that SOME TIMES the request work nice, makes me think that the issue is not on the server.js file (where I defined the endpoints), and also is not on my controllers files (where I have some logic and the requests itself).
I'll leave here some pics as example of what is happening but if you need some extra info just tell me:
A simple login example, I just fill the fields and send the request
And here you can see how the request remain as pending
Until it fails
EDIT: I'm using package Mysql2 to connect to the DB, and I was reading that this behavior may be because a bad use of connections (and I'm reading about "pools", but I'm kinda lost tbh)
Here is the connection file:
require("dotenv").config();
const mysql = require("mysql2");
const db = mysql.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
waitForConnections: true,
});
const connection = async () => {
db.connect((err) => {
if (err) throw err;
console.log("Successfully connected");
})
}
exports.db = db;
exports.connection = connection;
The first call to the DB (just to check the connection)
connection().then(() => {
app.listen(port, () => {
console.log(`Server running at ...`);
});
});
And the login logic
app.post("/dev-end/api/login", async (req, res) => {
await singleAccount(db, req.body.email)
.then(async (response) => {
if (response.code) {
res.render("templateLogin");
}
try {
if (await bcrypt.compare(req.body.password, response.password)) {
const user = { id: response._id, name: response.name };
await deleteTokenById(db, user.id.toString());
const accessToken = generateAccessToken(user);
const refreshToken = jwt.sign(
user,
process.env.REFRESH_TOKEN_SECRET,
{ expiresIn: "604800s" }
);
createToken(db, {
_id: user.id,
accessToken: accessToken,
refreshToken: refreshToken,
createdAt: new Date().toISOString().slice(0, 19).replace("T", " "),
}).then(
res
.cookie("access_token", accessToken, {
httpOnly: true,
maxAge: 60000 * 60 * 24 * 7,
})
.redirect("/dev-end/dashboard")
);
} else {
res.render("templateLogin");
}
} catch {
res.status(500).send();
}
})
.catch(console.log);
});
=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>
const singleAccount = async (conn, email) => {
return await read(conn).then((res) => {
if (!res.code) {
const result = res.find((e) => e.email.toString() === email);
if (!result) {
return {
code: 404,
msg: "No account was found with the provided id",
};
}
return result;
}
return res;
});
};
=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>=>
const read = async (conn) => {
const sql = `SELECT * FROM accounts`;
return await conn.promise().query(sql)
.then(([res, fields]) => res);
};

NodeJS Mysql pool.query() not releasing connections?

I am having trouble with pooling mysql connections with nodeJS. As I understand it, when creating a pool, I should be able to use pool.query() to:
Get a connection
Run my query
Release the connection
However, the issue I am running into is the connections remain open and "sleeps" until the server closes the connection itself (60 seconds). Is there something I am doing wrong here? For context, I am connecting to Heroku clearDB and am viewing the connection on its dashboard.
Example: Upon login, I make a query to check login credentials to authenticate, another query to fetch one set of data, and another query to fetch another set. After logging in, the server is left with 2 connection in "sleep" mode. They do not disconnect until 60 seconds expire.
Here is my db.js file:
const mysql = require("mysql");
const dbConfig = require("./db.config.js");
const connection = mysql.createPool({
host: dbConfig.HOST,
user: dbConfig.USER,
password: dbConfig.PASSWORD,
database: dbConfig.DB,
port: dbConfig.PORT,
multipleStatements: true,
connectionLimit: 10
})
module.exports = connection;
Here is how I am making queries:
const sql = require("./db.js"); //Our db connection
---OMITTED---
return new Promise((resolve, reject) => {
const select_user = "SELECT user_id, first_name, last_name, username, password, is_admin, is_active FROM users WHERE username = ? LIMIT 1"
const params = [username]
const user_pass = password
sql.query(select_user, params, (err, res) => {
if (res) {
if (res.length) {
const user = res[0]
const hash = user.password
const is_active = user.is_active
if (is_active) {
bcrypt.compare(user_pass, hash).then(res => {
if (res) {
resolve({ result: true, info: { fname: user.first_name, lname: user.last_name, username: user.username, is_admin: user.is_admin, user_id: user.user_id } })
} else {
reject({ result: false, msg: "wrong_creds" })
}
}).catch(err => {
reject({ result: false, msg: err })
})
} else {
reject({ result: false, msg: "inactive" })
}
} else {
reject({ result: false, msg: "user_not_exist" })
}
} else {
console.log("MYSQL QUERY, COULD NOT SELECT USER FOR AUTHENTICATION")
reject({ result: false, msg: err })
}
})
})
I'm under the impression that pool.query() will close the connection for me after each query. Is this not the case? Am I missing something once the query has been completed?
I have also tried the manual way:
const select_string = "SELECT * FROM user_backlogs WHERE movie_id = ? AND user_id = ?"
const params = [movie_id, user_id]
sql.getConnection((err, connection) => {
if (err) reject(err)
else {
connection.query(select_string, params, (err, res) => {
connection.release()
if (err) reject(err)
else {
if (res.length) {
resolve([movie_id, "exists", res[0]["added_on"]])
} else {
resolve([movie_id, "not_exists"])
}
}
})
}
})
But still, the connections remain up until the server kicks them off. Any help is greatly appreciated.
The pool will not close the connection. It will release the connection, which me means it can be reused by another query. The pool does this to optimize performance, since it takes time to open a new connection.
If you want to close the connection after use, you can explicitly destroy it (connection.destroy()) and the pool will create a new one the next time you issue a query. You can find more information on this in the documentation under pooling connections.

convert a NodeJS lambda function (AWS) to use "async" (promises, etc.) instead of callbacks

I have a lambda function that connects to mysql and runs a set of queries, but I actually have a sequence of mysql queries that need to run one after another. I.e., the value of one query is used in the next query, etc.
Currently, I have a bunch of callbacks to achieve this, but this is leading to "callback hell". How would I rewrite this to use async / await?
My code is actually split into 2 files. The first file does an initial query, and then the value is passed into a function of the second file. Please note that the mysql node_module is included but not shown here. The AWS API gateway calls index.js
// index.js
var mysql = require('mysql'); // from node_modules
var config = require('./config.json');
var dashboard = require('./dashboard.js');
var pool = mysql.createPool({
host : config.dbhost,
user : config.dbuser,
password : config.dbpassword,
database : config.dbname
});
exports.handler = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false;
pool.getConnection(function(err, connection) {
// check for mysql connection error first
if ( err ) {
throw err;
}
let qry = "select id from some_table where some_field = ?";
let someval = event.queryStringParameters.someval;
connection.query(qry, [someval], function(error, result) {
if ( error ) {
throw err;
}
else {
dashboard.processRequest(connection, callback, event, res[0].id);
}
});
});
}
// dashboard.js
module.exports = {
jsonResponse: function(results) {
return {
"statusCode": 200,
"body": JSON.stringify({ results }),
"isBase64Encoded": false,
"headers": {
"Access-Control-Allow-Origin": "*"
}
};
},
processRequest: function(connection, callback, event, val) {
let qry = "update first_table set some_field = ?";
connection.query(qry, [val], function(error, results) {
// return to client if error
if (error) {
callback(null, this.jsonResponse(error));
}
else {
// assume that this table must be update AFTER the previous statement
qry = "select id from second_table where some_field = ?";
connection.query(qry, [val], function(error1, results1) {
// return to client if error
if ( error1 ) {
callback(null, this.jsonResponse(error1));
}
qry = "update third_table set some_field = ? where id = ?";
connection.query(qry, [results1[0].id], function(error2, results2) {
// release connection when all queries are completed
connection.release();
if ( error2 ) {
callback(null, this.jsonResponse(error2));
}
else {
callback(null, this.jsonResponse(results2));
}
});
});
}
});
}
};
It was suggested to me that something like the below code might work. Unfortunately, it does not. I was curious to know why using try...catch blocks in the way shown below is not working, and is it the same thing as what you've shown, but just written differently?
// index.js
var mysql = require('mysql'); // from node_modules
var config = require('./config.json');
var dashboard = require('./dashboard.js');
var pool = mysql.createPool({
host : config.dbhost,
user : config.dbuser,
password : config.dbpassword,
database : config.dbname
});
exports.handler = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false;
pool.getConnection(function(err, connection) {
// check for mysql connection error first
if ( err ) {
throw err;
}
let qry = "select id from users where username = ? limit 1;";
let username = event.queryStringParameters.username;
try {
let res = await connection.query(qry, [event.queryStringParameters.username]);
dashboard.processRequest(connection, callback, event, res[0].id);
} catch (err) {
console.log(err);
}
});
}
// dashboard.js
module.exports = {
jsonResponse: function (results) {
return {
"statusCode": 200,
"body": JSON.stringify({results}),
"isBase64Encoded": false,
"headers": {
"Access-Control-Allow-Origin": "*"
}
};
},
processRequest: async function (connection, callback, event, val) {
let qry = "update first_table set some_field = ?";
try {
let results = await connection.query(qry, [val]);
qry = "select id from second_table where some_field = ?";
try {
let results1 = await connection.query(qry, [val]);
qry = "update third_table set some_field = ? where id = ?";
try {
let results2 = await connection.query(qry, [results1[0].id]);
connection.release();
callback(null, this.jsonResponse(results2));
} catch (error2) {
callback(null, this.jsonResponse(error2));
}
} catch (error1) {
callback(null, this.jsonResponse(error1));
}
} catch (error) {
callback(null, this.jsonResponse(error));
}
}
};
We need use promises.
Typically I follow this approach:
Create one async method mainProcess and have bunch of methods step by step called with in that method. one after the other with await or all at once.
Each async method getConnection and runQuery in this case, called within mainProcess must a Promise.
If any errors from these methods i.e promise rejects from individual methods, goes in catch block of mainProcess().
If no errors, all methods within mainProcess gets executed and goes to then block of mainProcess()
Your code can be refactored like this (just wrote in an editor untested)
var pool = mysql.createPool({
host: config.dbhost,
user: config.dbuser,
password: config.dbpassword,
database: config.dbname,
});
exports.handler = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false;
/**
* Main Lambda Process
*/
const mainProcess = async () => {
// Get Connection
let connection = await getConnection();
// Run Step 1
let qry1 = "select id from some_table1 where some_field = ?";
const response1 = await runQuery(connection, qry1, { someFiledValue: 1222})
// Run Step 2
let qry2 = "select id from some_table2 where some_field = ?";
const resonse2 = await runQuery(connection, qry2, { someFiledValue: 1222})
return 'All Good';
});
}
mainProcess()
.then(result => {
// All lambda success messages are returned from here
callback(null, result);
})
.catch(error => {
// All lambda errors thrown from here
callback(error);
});
};
function getConnection(qry, parms) {
return new Promise((resolve, reject) => {
pool.getConnection(function (error, connection) {
if (error) {
// return to client if error
reject(error);
} else {
// Return response
resolve(connection);
}
});
});
}
/**
* Runs a query, either resolves or rejects
*/
function runQuery(connection, qry, parms) {
return new Promise((resolve, reject) => {
connection.query(qry, [val], function (error, results) {
if (error) {
// return to client if error
reject(error);
} else {
// Return response
resolve(result);
}
});
});
}
When you're dealing with a lambda function which performs an async task you have two solutions:
you can use non async handlers, in which case you need to invoke "callback" on promises as you did in your example
you can use async handlers, which does not requires the "callback" input and that allows you to write async/await code, like the following example:
const mysql = require('mysql2/promise');
exports.handler = async(event, context) => {
//get path variable
const { pathVar } = event.pathParameters;
// get connection
const connection = await mysql.createConnection({
host : process.env.RDS_HOSTNAME,
user : process.env.RDS_USERNAME,
password : process.env.RDS_PASSWORD,
database : process.env.RDS_DB_NAME
});
// get text query
const textQuery = `SELECT field FROM entity WHERE attribute = ${pathVar}`;
// get res
const results = await connection.execute(textQuery);
return {
"statusCode": 200,
"body": results,
"isBase64Encoded": false
}
}
You can have a look at the AWS docs: https://docs.aws.amazon.com/lambda/latest/dg/nodejs-handler.html

Code running in wrong order after added connection pool (async/await needed?)

I have a NodeJS API which was using 'normal connections' to a MYSQL DB and running well execpt I was having disconnect issues.
I have implemented pooling now and that is working however it seems some code is now running out of order due to the new nature of the connections.
I've never used async/await as I'm very new to coding but I've tried to do it here to get the response I need.
Pretty much I have put in console logs to see the order it is running and instead of gettting "1,2,3", I'm getting "2,3,1" which obviously is going to give me the wrong results as I need to get query data before proceeding.
Can someone show how to get this await system working?
The first section gets the MAC and ID from the user and then checks if this exists in my DB already. If it does then it updates the dateTime of recent login. If it Doesnt then it adds the MAC.
The issue is that I'm not getting my response regarding if the mac exists, so it always is "false" therefore the mac keeps getting added over and over as the it isnt waiting for the very first query result!
router.post('/updateComp/',verify,async (req,res) => {
//console.log(req.params.MAC)
var sqlString = "SET #chemistID = ?; SET #MAC = ?; Call checkMAC(#chemistID,#MAC)";
try{
const MAC = req.body.MAC;;
const compName = req.body.compName;
var compCount = 0;
var MACExists = false;
console.log(MAC + " " + compName);
await connection.query(sqlString,[req.user._id,MAC], (err,rows,fields)=>{
console.log("Check 1");
if(!err){
rows.forEach(element => {
if(element.constructor == Array){
compCount = element[0].compCount;
MACExists = element[0].MACExists;
console.log(compCount);
console.log(MACExists);
}
else{
//array not returned?
return res.status(500);
}
})
}else{
//sql con error?
return res.status(500);
}
console.log("comcount = " + compCount);
})
console.log("Check 2");
if(compCount == 0 || (compCount < 7 && MACExists == false)){
//Insert new comp
var sqlString = "INSERT INTO tblLicense (chemistID,compName,MAC,lastAccess) VALUES (?,?,?,current_timestamp());";
console.log("Check 3");
connection.query(sqlString,[req.user._id,compName,MAC], (err,rows,fields)=>{
if(!err){
console.log("New terminal added for " + req.user._id);
return res.status(200).json({
Result: true,
compAdded: true
})
}else{
console.log("Failed to add new computer to sub " + req.user._id);
return res.status(500).json({
Result: false,
compAdded: false,
Comment: "Failed to add new computer to sub"
})
}
})
}else{
if (compCount == 7){
if(MACExists){
return res.status(200).json({
Result: true
})
}else{
return res.status(200).json({
Result: false,
compAdded: false,
Comment: compCount
})
}
}else{
//Update time of current comp access
var sqlString = "UPDATE tblLicense SET lastAccess = current_timestamp() WHERE MAC = ? AND chemistID = ?;";
connection.query(sqlString,[MAC,req.user._id], (err,rows,fields)=>{
if(!err){
return res.status(200).json({
Result: true,
compAdded: false
})
}
else
{
return res.status(500).json({
Result: false,
compAdded: false
})
}
})
}
}
} catch (e) {
// this catches any exception in this scope or await rejection
console.log(e);
res.status(500).json({ Result: e });
}
});
Connection Config:
const mysql = require('mysql');
var pool = mysql.createPool({
host:'localhost',
user: '1234',
password: '1234',
database : '1234',
multipleStatements: true,
connectionLimit: 10
});
pool.getConnection((err, connection) => {
if (err) {
if (err.code === 'PROTOCOL_CONNECTION_LOST') {
console.error('Database connection was closed.')
}
if (err.code === 'ER_CON_COUNT_ERROR') {
console.error('Database has too many connections.')
}
if (err.code === 'ECONNREFUSED') {
console.error('Database connection was refused.')
}
}
if (connection) connection.release()
return
})
module.exports ={
connection : pool
}
Checking https://github.com/mysqljs/mysql doesn't seem connection.query ever returns a Promise.
You can still use async/await by wrapping connection.query inside a promise.
Here's a post that explains how to do it https://medium.com/wenchin-rolls-around/example-of-using-transactions-with-async-await-via-mysql-connection-pool-9a37092f226f
And looks like another option is to use Bluebird How to promisify a MySql function using bluebird?

node.js + mysql connection pooling

I'm trying to figure out how to structure my application to use MySQL most efficent way. I'm using node-mysql module. Other threads here suggested to use connection pooling so i set up a little module mysql.js
var mysql = require('mysql');
var pool = mysql.createPool({
host : 'localhost',
user : 'root',
password : 'root',
database : 'guess'
});
exports.pool = pool;
Now whenever I want to query mysql I require this module and then query the databse
var mysql = require('../db/mysql').pool;
var test = function(req, res) {
mysql.getConnection(function(err, conn){
conn.query("select * from users", function(err, rows) {
res.json(rows);
})
})
}
Is this good approach? I couldn't really find too much examples of using mysql connections besides very simple one where everything is done in main app.js script so I don't really know what the convention / best practices are.
Should I always use connection.end() after each query? What if I forget about it somewhere?
How to rewrite the exports part of my mysql module to return just a connection so I don't have to write getConnection() every time?
It's a good approach.
If you just want to get a connection add the following code to your module where the pool is in:
var getConnection = function(callback) {
pool.getConnection(function(err, connection) {
callback(err, connection);
});
};
module.exports = getConnection;
You still have to write getConnection every time. But you could save the connection in the module the first time you get it.
Don't forget to end the connection when you are done using it:
connection.release();
You should avoid using pool.getConnection() if you can. If you call pool.getConnection(), you must call connection.release() when you are done using the connection. Otherwise, your application will get stuck waiting forever for connections to be returned to the pool once you hit the connection limit.
For simple queries, you can use pool.query(). This shorthand will automatically call connection.release() for you—even in error conditions.
function doSomething(cb) {
pool.query('SELECT 2*2 "value"', (ex, rows) => {
if (ex) {
cb(ex);
} else {
cb(null, rows[0].value);
}
});
}
However, in some cases you must use pool.getConnection(). These cases include:
Making multiple queries within a transaction.
Sharing data objects such as temporary tables between subsequent queries.
If you must use pool.getConnection(), ensure you call connection.release() using a pattern similar to below:
function doSomething(cb) {
pool.getConnection((ex, connection) => {
if (ex) {
cb(ex);
} else {
// Ensure that any call to cb releases the connection
// by wrapping it.
cb = (cb => {
return function () {
connection.release();
cb.apply(this, arguments);
};
})(cb);
connection.beginTransaction(ex => {
if (ex) {
cb(ex);
} else {
connection.query('INSERT INTO table1 ("value") VALUES (\'my value\');', ex => {
if (ex) {
cb(ex);
} else {
connection.query('INSERT INTO table2 ("value") VALUES (\'my other value\')', ex => {
if (ex) {
cb(ex);
} else {
connection.commit(ex => {
cb(ex);
});
}
});
}
});
}
});
}
});
}
I personally prefer to use Promises and the useAsync() pattern. This pattern combined with async/await makes it a lot harder to accidentally forget to release() the connection because it turns your lexical scoping into an automatic call to .release():
async function usePooledConnectionAsync(actionAsync) {
const connection = await new Promise((resolve, reject) => {
pool.getConnection((ex, connection) => {
if (ex) {
reject(ex);
} else {
resolve(connection);
}
});
});
try {
return await actionAsync(connection);
} finally {
connection.release();
}
}
async function doSomethingElse() {
// Usage example:
const result = await usePooledConnectionAsync(async connection => {
const rows = await new Promise((resolve, reject) => {
connection.query('SELECT 2*4 "value"', (ex, rows) => {
if (ex) {
reject(ex);
} else {
resolve(rows);
}
});
});
return rows[0].value;
});
console.log(`result=${result}`);
}
You will find this wrapper usefull :)
var pool = mysql.createPool(config.db);
exports.connection = {
query: function () {
var queryArgs = Array.prototype.slice.call(arguments),
events = [],
eventNameIndex = {};
pool.getConnection(function (err, conn) {
if (err) {
if (eventNameIndex.error) {
eventNameIndex.error();
}
}
if (conn) {
var q = conn.query.apply(conn, queryArgs);
q.on('end', function () {
conn.release();
});
events.forEach(function (args) {
q.on.apply(q, args);
});
}
});
return {
on: function (eventName, callback) {
events.push(Array.prototype.slice.call(arguments));
eventNameIndex[eventName] = callback;
return this;
}
};
}
};
Require it, use it like this:
db.connection.query("SELECT * FROM `table` WHERE `id` = ? ", row_id)
.on('result', function (row) {
setData(row);
})
.on('error', function (err) {
callback({error: true, err: err});
});
I am using this base class connection with mysql:
"base.js"
var mysql = require("mysql");
var pool = mysql.createPool({
connectionLimit : 10,
host: Config.appSettings().database.host,
user: Config.appSettings().database.username,
password: Config.appSettings().database.password,
database: Config.appSettings().database.database
});
var DB = (function () {
function _query(query, params, callback) {
pool.getConnection(function (err, connection) {
if (err) {
connection.release();
callback(null, err);
throw err;
}
connection.query(query, params, function (err, rows) {
connection.release();
if (!err) {
callback(rows);
}
else {
callback(null, err);
}
});
connection.on('error', function (err) {
connection.release();
callback(null, err);
throw err;
});
});
};
return {
query: _query
};
})();
module.exports = DB;
Just use it like that:
var DB = require('../dal/base.js');
DB.query("select * from tasks", null, function (data, error) {
callback(data, error);
});
When you are done with a connection, just call connection.release() and the connection will return to the pool, ready to be used again by someone else.
var mysql = require('mysql');
var pool = mysql.createPool(...);
pool.getConnection(function(err, connection) {
// Use the connection
connection.query('SELECT something FROM sometable', function (error, results, fields) {
// And done with the connection.
connection.release();
// Handle error after the release.
if (error) throw error;
// Don't use the connection here, it has been returned to the pool.
});
});
If you would like to close the connection and remove it from the pool, use connection.destroy() instead. The pool will create a new connection the next time one is needed.
Source: https://github.com/mysqljs/mysql
You can use this format as I used
const mysql = require('mysql');
const { HOST, USERNAME, PASSWORD, DBNAME, PORT } = process.env;
console.log();
const conn = mysql.createPool({
host: HOST,
user: USERNAME,
password: PASSWORD,
database: DBNAME
}, { debug: true });
conn.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
if (error) throw error;
console.log('Db is connected - The solution is: ', results[0].solution);
});
module.exports = conn;
Using the standard mysql.createPool(), connections are lazily created by the pool. If you configure the pool to allow up to 100 connections, but only ever use 5 simultaneously, only 5 connections will be made. However if you configure it for 500 connections and use all 500 they will remain open for the durations of the process, even if they are idle!
This means if your MySQL Server max_connections is 510 your system will only have 10 mySQL connections available until your MySQL Server closes them (depends on what you have set your wait_timeout to) or your application closes! The only way to free them up is to manually close the connections via the pool instance or close the pool.
mysql-connection-pool-manager module was created to fix this issue and automatically scale the number of connections dependant on the load. Inactive connections are closed and idle connection pools are eventually closed if there has not been any activity.
// Load modules
const PoolManager = require('mysql-connection-pool-manager');
// Options
const options = {
...example settings
}
// Initialising the instance
const mySQL = PoolManager(options);
// Accessing mySQL directly
var connection = mySQL.raw.createConnection({
host : 'localhost',
user : 'me',
password : 'secret',
database : 'my_db'
});
// Initialising connection
connection.connect();
// Performing query
connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
if (error) throw error;
console.log('The solution is: ', results[0].solution);
});
// Ending connection
connection.end();
Ref: https://www.npmjs.com/package/mysql-connection-pool-manager
i always use connection.relase(); after pool.getconnetion like
pool.getConnection(function (err, connection) {
connection.release();
if (!err)
{
console.log('*** Mysql Connection established with ', config.database, ' and connected as id ' + connection.threadId);
//CHECKING USERNAME EXISTENCE
email = receivedValues.email
connection.query('SELECT * FROM users WHERE email = ?', [email],
function (err, rows) {
if (!err)
{
if (rows.length == 1)
{
if (bcrypt.compareSync(req.body.password, rows[0].password))
{
var alldata = rows;
var userid = rows[0].id;
var tokendata = (receivedValues, userid);
var token = jwt.sign(receivedValues, config.secret, {
expiresIn: 1440 * 60 * 30 // expires in 1440 minutes
});
console.log("*** Authorised User");
res.json({
"code": 200,
"status": "Success",
"token": token,
"userData": alldata,
"message": "Authorised User!"
});
logger.info('url=', URL.url, 'Responce=', 'User Signin, username', req.body.email, 'User Id=', rows[0].id);
return;
}
else
{
console.log("*** Redirecting: Unauthorised User");
res.json({"code": 200, "status": "Fail", "message": "Unauthorised User!"});
logger.error('*** Redirecting: Unauthorised User');
return;
}
}
else
{
console.error("*** Redirecting: No User found with provided name");
res.json({
"code": 200,
"status": "Error",
"message": "No User found with provided name"
});
logger.error('url=', URL.url, 'No User found with provided name');
return;
}
}
else
{
console.log("*** Redirecting: Error for selecting user");
res.json({"code": 200, "status": "Error", "message": "Error for selecting user"});
logger.error('url=', URL.url, 'Error for selecting user', req.body.email);
return;
}
});
connection.on('error', function (err) {
console.log('*** Redirecting: Error Creating User...');
res.json({"code": 200, "status": "Error", "message": "Error Checking Username Duplicate"});
return;
});
}
else
{
Errors.Connection_Error(res);
}
});