NodeJS Mysql end function stopped working? - mysql

been building a website with a mysql database using the nodejs mysql package.
Stopped working on it for a couple weeks.
With no changes to code, come back and realize that the end function in mysql package appears to no longer be working.
I use an async function like so:
app.get('/', (req, res) => {
async function homeResponse(){
try{
var db = createConnection();
await conquerie.connect(db);
// get stuff from db
await conquerie.end(db);
}catch(err){
console.log(err);
res.render('error');
}
}
homeResponse();
});
conquerie js mentioned above uses:
function connect(db){
let connectpromise = new Promise(function(resolve, reject){
db.connect((err) => {
if(err){
console.log('ERROR COULD NOT CONNECT NERD');
reject(err);
}
console.log('Connected to the DB!!!');
resolve();
});
});
return connectpromise;
}
function end(db){
let endpromise = new Promise(function(resolve, reject){
db.end((err) =>{
if(err){
console.log('cant end connecty');
reject(err);
}
console.log('DB Connection ended!!!');
resolve();
});
});
return endpromise;
}
DB Connect works fine, Info pulls from DB with no issues, end does not work.
It catches an error on db.end and returns 'can't end connecty'.
Connection does not end. If I remove that catch, I get a PROTOCOL_SEQUENCE_TIMEOUT error.
I have tried async and sync, no change.
Have latest version of mysql package, and no one else online is mentioning this so It's gotta be something I did I guess.
Any Advice is much appreciated. Thanks!~

Related

Connecting to MySql database from AWS Lambda function using Node.js, no connect callback

I am trying to connect an external (not AWS) MySql server from an AWS Lambda function written in Node.js using nodejs14.x environment, but the connect() callback is not called.
I am been struggling with this problem since days, there are a lot of references to similar issues but I really tried all possible permutations of solutions I found.
I am deploying with SAM and testing both on local machine and on real AWS.
Here is the sample code of the lambda helper
const mysql = require('mysql');
exports.helloFromLambdaHandler = async () => {
const message = 'Hello from Lambda!';
console.info(`${message}`);
var sql = "SELECT 1+? AS sum";
var values = [1];
console.log("Doing createConnection");
const connection = mysql.createConnection({
/* my connection data */
});
console.log("Doing connect");
connection.connect( (err) => {
console.log("Inside connection callback");
console.log('connected as id ' + connection.threadId);
if(!err) {
console.log("DB connected, thread id is " + connection.threadId);
console.log("Doing query");
connection.query(sql, values, (err, result, values) => {
console.log("Inside query callback");
if(!err) {
console.log("Query ok!");
console.log(result);
connection.end();
} else {
console.log("Error executing query: " + err.message);
}
});
} else {
console.log("Error connecting db: "+ err.message);
}
});
console.log ("Returning...");
return message;
}
The log is
Hello from Lambda!
Doing createConnection
Doing connect
Returning...
The expected behaviour is that after "Returning..." I should see the log "Inside connection callback" then "Inside query callback" and then "Query ok!".
Instead the callback of connect() appears not invoked.
I know that I can call query() directly skipping connect() but also doing so I encounter same issue.
Any clue?
Thank you!
SOLUTION
As suggested by the accepted answer, returning a promise is the solution to let Node complete all the queue. Unfortunately it's not possible to complete the Lambda and leave it running in background in a safe manner, for what I understand.
I am investigating alternative solutions such as:
mysql2 library which supports promises natively
serverless-mysql npm package which handles shared db connections
Below the running demo code
const mysql = require('mysql');
exports.helloFromLambdaHandler = async (event, context) => {
const message = 'Hello from Lambda!';
console.info(`${message}`);
var sql = "SELECT 1+? AS sum";
var values = [1];
console.log("Doing createConnection");
const connection = mysql.createConnection({
/* my connection data */
});
console.log("Doing query");
const promise = new Promise( (resolve, reject) => {
connection.query(sql, values, (err, result, values) => {
console.log("Inside query callback");
if(!err) {
console.log("Query ok!");
console.log(result);
connection.end();
resolve(message);
} else {
console.log("Error executing query: " + err.message);
reject(err);
}
});
});
console.log ("Returning...");
return promise;
}
You are using async handler, thus your function probably completes before your connect() has a chance to execute.
To try to overcome the issue, you can use Promise as shown in AWS docs.

NodeJS mysql app freezing without error - how to diagnose

My Node app is freezing when running a function I've written. The code will stop executing at a specific line on the 11th loop, with no error message. No further requests can be made to the app, and it must be restarted. The data is changing every time it's run, and it is always the 11th iteration.
The function it is calling is relatively complex, so I can't put the code here. My question is how do you approach diagnosing a piece of code when you see no failure notices? I assume the problem is mysql-related, as the last thing logged in the simplified version of the code below is 'Org request start 11' - no error message ever follows. But I don't understand how the code can stop executing here without entering the callback.
Example code is here:
async function processDataset(datasets){
for (let i = 0; i < datasets.length; i++) {
const dataset= datasets[i];
const orgData = await getOrgData(dataset.id);
const parsedDataset = await processDataset(dataset, orgData);
}
}
function getOrgData(datasetId) {
return new Promise(function (resolve, reject) {
console.log("Org request start", datasetId);
connection.getConnection(function (err, connection) {
console.log("got connection");
if (err) {
console.log(err);
reject(err);
}
connection.query("select * from orgs;", function (error, rows, fields) {
console.log("query returned");
connection.release();
if (error) {
console.log(error);
reject(error);
}
resolve(rows);
});
});
});
}
Running Node v12 / Express, mysql 5.5
So I found the problem was that elsewhere I had a query running that was missing a line to release the mysql connection in the second function called. Adding this resolved the bug. I don't understand why this doesn't trigger an error, or how I would have gone about diagnosing this with a more systematic approach, so would like to hear any comments.

connection.query(...).then is not a function

I am new to the node js . I am using node with express in my backend and mysql as database . I have the confusion while handling the async calling . In my code while i use .
return connection.query(qry).then(
function(result) {
console.log('Query executed');
resolve(result.rows[0]);
},
function(err) {
console.log('Error occurred', err);
reject(err);
}
)
I got error connection.query(...).then is not a function
connection.query(qry, function (err, rows, fields) {
});
is executed correctly.
Simple query i am not getting any problem . while execute the complex query the above one is not wait for complete query execution
To use .then() with mysql first you need to “promisify” the database client.That can be done by creating a wrapper class for the MySQL client.
Check this article for better understanding
I have not found that, we can use promise with connection.query('') function. As per mysqljs documentation we can pass callback function for getting result.
var mysql = require('mysql');
var connection = mysql.createConnection(...);
connection.query('SELECT * FROM table_name', function (error, results, fields) {
if (error) throw error;
console.log(result);
});
You need to import mysql, and also actually create the connection.
Just do:
var mysql=require('mysql');
var connection=mysql.createConnection({
host:'127.0.0.1',
port: '3306',
user:'root',
password:'12345',
database:'db'
});
connection.connect(function(error){
if(!!error){
console.log(error);
}else{
console.log('Connected!:)');
}
});

Node.JS and MySQL - queries lock up and execute extremely slowly

I am getting strange behavior using Node.JS and MySQL with this driver - https://github.com/mysqljs/mysql
Essentially, I have a button on the frontend that triggers an app.get that makes a query in the database and I can happily use the results in my backend.
This works nicely, until I press the button 4-5 times in a second, where as the queries lock up and I have to wait for 2-3 minutes until they continue executing. I have a similar write function that behaves the same way.
Is it possible this is a problem, because I'm trying to execute the exact same query asynchronously? I.e. do I have to limit this from the front end or is it a backend problem?
Any ideas on how to debug what exactly is going on?
// database.js
var mysql = require('mysql');
var pool = mysql.createPool({
connectionLimit: 100,
host : 'localhost',
user : 'secret',
password : 'secret',
database : 'mydb'
});
exports.getConnection = function(callback) {
pool.getConnection(function(err, connection) {
callback(err, connection);
});
};
// dbrw.js
var con = require('../config/database');
function read(id, done) {
con.getConnection(function(err, connection){
if(!err){
connection.query("SELECT * FROM users WHERE id = ?",[id], function(err, rows) {
connection.release();
if (err)
done(err);
if (rows.length) {
console.log("rows " + JSON.stringify(rows));
done(rows[0].progress);
};
});
}
else {
console.log(err);
}
});
}
exports.read = read;
// routes.js
var dbrw = require('./dbrw.js');
app.get('/read', isLoggedIn, function(req, res) {
dbrw.read(req.user.id, function(result) {
console.log(result);
});
});
// Frontend - angular app.js
$scope.tryread = function() {
$http.get('/read');
}
Thanks in advance for any input.
I see a few issues:
function read(id, done) {
con.getConnection(function(id, connection){...}
}
Notice how you overwrite the id passed to read by giving that same name to an argument of the callback to getConnection.
Also, your Express route doesn't actually end the request by sending back a response, which will make your browser time out the connection. At some point, it will even refuse to send more requests because too many are still pending.
So make sure to end the request:
app.get('/read', isLoggedIn, function(req, res) {
dbrw.read(req.user.id, function(result) {
console.log(result);
res.end(); // or `res.send(result)`
});
});
And a tip: you should use the callback calling convertion for Node, where the first argument represents an error (if there is any) and the second argument represents the return value.

Node.js, Express and Mysql. How is correct way

What i'am trying to achieve is to make DB query inside closure. Return data and then send stuff to user. I understand that best practice is to use database pooling. Problem is that query is not sync.
Simplified code:
server.js
var express = require('express'),
app = express(),
server = require('http').createServer(app),
mysql = require('mysql');
app.set('DB:pool', mysql.createPool(process.env.DATABASE_URL));
var myClosure = require('./closure.js')(app));
app.get('/somepage', function(req, res) {
var data = myClosure.myquery();
res.send(data);
});
app.get('/anotherpage', function(req, res) {
var data = myClosure.myquery();
res.send(data);
});
app.listen(3000);
closure.js
function myClosure(app) {
var pool = app.get('DB:pool');
return {
myquery: function(inp) {
pool.getConnection(function(err, db) {
if (err) throw err;
db.query('SELECT * FROM table', function(err, rows, fields) {
if (err) throw err;
data = rows[0]
db.release();
});
});
return data;
}
};
}
module.exports = myClosure;
In examples i found all DB related stuff were made in route callback and response was sent in query callback. But way i'm trying to do it is not working as myquery returns undefined because sql query is not done there.
So what is correct way to handle querys ?
Make your query-function handle a callback too:
// server.js
app.get('/somepage', function(req, res) {
myClosure.myquery(function(err, data) {
// TODO: handle error...
res.send(data);
});
});
// closure.js
...
myquery: function(callback) {
pool.getConnection(function(err, db) {
if (err) return callback(err);
db.query('SELECT * FROM table', function(err, rows, fields) {
// release connection before we return anything, otherwise it
// won't be put back into the pool...
db.release();
if (err) return callback(err);
callback(null, rows[0]);
});
});
}
(I left out the inp argument because that didn't seem to be used)