NodeJS - Connecting to a local Mysql Database - mysql

I am trying to create a mysql database connection for my node app and ran sequelize.authenticate().then(function(errors) { console.log(errors) }); to test if the connection worked. The response that is logged to my console is Executing (default): SELECT 1+1 AS result undefined The undefined portion makes me think that the connection either didn't work or that there isn't any database found. I can't seem to figure that out. I thought by creating a database through Sequel Pro and connecting to localhost via the Socket, I can use the same credentials for connecting with my Node app. Do I need to create a file within my app for the database and not use the Sequel Pro database?
Controller file (where the connection is created):
var Sequelize = require('sequelize');
var sequelize = new Sequelize('synotate', 'root', '', {
host:'localhost',
port:'3306',
dialect: 'mysql'
});
sequelize.authenticate().then(function(errors) { console.log(errors) });
var db = {}
db.Annotation = sequelize.import(__dirname + "/ann-model");
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
ann-model.js (where my table is being defined):
module.exports = function(sequelize, DataTypes) {
var Ann = sequelize.define('annotations', {
ann_id: {
type: DataTypes.INTEGER,
primaryKey: true
},
ann_date: DataTypes.DATE,
}, {
freezeTableName: true
});
return Ann;
}

Try this one, Executing (default): SELECT 1+1 AS result means that everything okay
sequelize
.authenticate()
.then(function(err) {
if (!!err) {
console.log('Unable to connect to the database:', err)
} else {
console.log('Connection has been established successfully.')
}
});
But i didn't know where you get undefined

Related

Add Data in Mongodb and Mysql in single button click

In this application i am adding data in mongodb which is working fine but at same time i need to implement Mysql. So when i register a user it should get save in Mongodb and in Mysql. My Code for Mysql Data Connection is sucessfull but data pushing is not happening(Mysql). Can anyone help me out yr. Thank you very much.
const {Sequelize} =require('sequelize');
const mysql= require('mysql');
var path1 = require('path');
var root_path = path1.dirname(require.main.filename);
var models = require(root_path+'/models');
router.post("/users", function(req, res) {
console.log("First In");
var user_id=req.query.user_id
var flag;
var userData = [];
var body_data =req.body.data;
//Mysql Start
const con = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'root',
database: 'tcexam'
});
con.connect((err) => {
if(err){
console.log('Error connecting to Db',err);
return;
}
console.log('Connection established');
});
models.userMysl.find({
email: body_data.email.toLowerCase()
})
console.log("Email---------->>>",email);
.then(function(country){
models.userMysl.create({
name: body_data.user_firstName,
lastname : body_data.user_lastname,
mother_name : body_data.motherName,
surname : body_data.Surname,
email: body_data.userEmail.toLowerCase(),
username:body_data.user_name,
password:body_data.user_password,
}).then(function(user) {
if(error){
console.log("Error",error);
}else {
res.send({
status: 200,
data:userData
});
}
});
});
});
//Mysql End
userModel.find({
"role": req.query.user_type
}).then(function(users) {
users.forEach(user => {
if(user.doc_id==''){
var user = {
id: user._id,
name: user.fullName,
status: user.status,
role: user.role,
email:user.email,
lastLoginDate: user.lastLoginDate,
lastLoginTime: user.lastLoginTime,
flag:'0'
}
userData.push(user);
}
else{
var usr = {
id: user._id,
name: user.fullName,
picture: `${filelink}/api/usersData/download?document_id=${user.doc_id}`,
status: user.status,
role: user.role,
email:user.email,
lastLoginDate: user.lastLoginDate,
lastLoginTime: user.lastLoginTime,
flag:'1'
}
userData.push(usr);
}
})
res.send({
status: 200,
data: userData
})
})
"use strict";
module.exports = function(sequelize, DataTypes) {
var userMysql = sequelize.define("tce_users", {
user_name: DataTypes.STRING(100),
user_password: DataTypes.STRING,
surname: DataTypes.STRING(100),
user_email: DataTypes.STRING(100),
user_firstName:DataTypes.STRING(100),
user_lastname:DataTypes.STRING(100),
user_birthdate:DataTypes.String(17),
user_birthplace:Datatypes.STRING(100),
user_regnumber:DataTypes.STRING(100),
user_ssn:DataTypes.STRING(100),
user_level:DataType.STRING(100),
user_verifycode:Datatypes.STRING(100)
});
return userMysql;
};
Since, Node JS is single threaded, after insertion into mysql line of code executes before establishment of connection with mysql db. Somehow connecting with mysql require time therefore next block code executes before connection happen.
Firstly, you need to change approach where you need to connect mysql,
Connection string probably should not be in the post api itself,
it's needs to be connect when application starts using some config utility.
Either you can choose promise to resolve the execution of insertion into
mysql or can use async await approach to insert the data after mysql
connection established.

Learning Node and issues with mysql query

i'm learning node and have hit an issue with running a mysql query. I am certain i am getting connectivity to the mysql db (as when i run the query from the same module as i connect to the DB i am able to print the rows to the console log). However i get a 500 error when i require the DB connection into my another file and use in the query. I've spent last few hours on stack overflow and still stuck. Its definitely not the function as if i just return text it works fine so its definitely something around the way i am utilising the db connection. The DB connection file is below:
// initialize database connection
const mysql = require('mysql')
var db;
function connectDatabase() {
if (!db) {
db = mysql.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_DATABASE
})
db.connect(function(err){
if(!err) {
console.log('Database is connected!')
} else {
console.log('Error connecting database!')
}
})
}
return db
}
module.exports = connectDatabase()
The module where the DB connection us used in query below:
const db = require('../db').connectDatabase
exports.getNightlyRatesData = () => {
//const { rows } = db.query('SELECT * FROM rate', function (err, rows) {
db.query('SELECT * FROM rate', function (err, rows) {
if (err) {
console.log("ERROR");
console.log(err);
return;
}
console.log("good");
})
return rows
}

Node MySQL Connection Pool - wait for database to start

How do I check if a MySQL database is ready for some queries from a Node MySQL Connection Pool?
I have a Docker environment consisting of thee containers:
container 1: web server
container 2: api
container 3: database
The database container runs a MySQL database. The api container connects to that database. All three containers are started at the same time. The web server container is up after 0,5s. The api container is up after 2s. The database server is up after 20s.
Currently, the api tries to access the tables of the database before the database is up and running. This leads to errors like connection refused. The following code segment always ends up with the message "Error querying database!" when the MySQL database is not yet up:
const sql: string = 'SELECT * FROM sometable;';
MySQL.createPool({
connectionLimit: 10,
acquireTimeout: 30000,
waitForConnections: true,
database: 'mydatabase',
host: 'localhost',
multipleStatements: true,
password: 'mypassword',
user: 'root',
}).query(sql, (err, result) => {
if (result) {
console.log('Successfully queried database.');
} else {
console.log('Error querying database!');
}
});
Versions in use:
OS: Ubuntu 19.10
Node: v13.6.0
MySQL (Node API): "#types/mysql": "2.15.8" and "mysql": "2.17.1"
MySQL (Docker Database): mysql:5.7.28
TypeScript: 3.7.4
I would like to check (and wait) the database readiness out of the api, possibly using the Connection Pool I use for queries. Is that possible?
Retry to connect with setTimeout():
(answer in Javascript rather than typescript)
'use strict';
const dbpool = require('mysql').createPool({
connectionLimit: 10,
acquireTimeout: 30000,
waitForConnections: true,
database: 'mydatabase',
host: 'localhost',
multipleStatements: true,
password: 'mypassword',
user: 'root',
});
const sql = 'SELECT * FROM sometable;';
const attemptConnection = () =>
dbpool.getConnection((err, connection) => {
if (err) {
console.log('error connecting. retrying in 1 sec');
setTimeout(attemptConnection, 1000);
} else {
connection.query(sql, (errQuery, results) => {
connection.release();
if (errQuery) {
console.log('Error querying database!');
} else {
console.log('Successfully queried database.');
}
});
}
});
attemptConnection();
Here is my test run:
$ sudo service mysql stop; node test.js & sudo service mysql start
[1] 24737
error connecting. retrying in 1 sec
error connecting. retrying in 1 sec
$ Successfully queried database.
FYI, The program never ends because it needs dbpool.end();
Your API should try to connect to the database with a timeout and a certain threshold of connection attempts. However, there are readily available solutions for this scenario.
Try using wait-for-mysql module.
waitForMy = require 'wait-for-mysql'
config =
username: user
password: pass
quiet: true
query: 'SELECT 1'
waitForMy.wait(config)
Here you have a variation but with no need to mysql pooling. I'm using this on my server and it does work:
const mysql = require('mysql')
var db // global, to use later to db.query
var dbInfo = {
host : 'example.org',
database : 'some_database',
user : 'bob',
password : 'secret'
}
function connectToDb(callback) {
const attemptConnection = () => {
console.log('Attempting to connect to db')
dbInfo.connectTimeout = 2000 // same as setTimeout to avoid server overload
db = mysql.createConnection(dbInfo)
db.connect(function (err) {
if (err) {
console.log('Error connecting to database, try again in 1 sec...')
db.destroy() // end immediately failed connection before creating new one
setTimeout(attemptConnection, 2000)
} else {
callback()
}
})
}
attemptConnection()
}
// now you simply call it with normal callback
connectToDb( () => {
console.log('Connection successfully')
// do some queries
db.query(..)
})

AWS Lambda and RDS working example (need it to work with Sequelize)

Here's a working example of AWS Lambda and MySQL, but I'd like it to work with Sequelize. How do I initialize Sequelize to work with AWS Lambda? I have the authenticated IAM role working too.
https://dzone.com/articles/passwordless-database-authentication-for-aws-lambd
'use strict';
const mysql = require('mysql2');
const AWS = require('aws-sdk');
// TODO use the details of your database connection
const region = 'eu-west-1';
const dbPort = 3306;
const dbUsername = 'lambda'; // the name of the database user you created in step 2
const dbName = 'lambda_test'; // the name of the database your database user is granted access to
const dbEndpoint = 'lambdatest-cluster-1.cluster-c8o7oze6xoxs.eu-west-1.rds.amazonaws.com';
module.exports.handler = (event, context, cb) => {
var signer = new AWS.RDS.Signer();
signer.getAuthToken({ // uses the IAM role access keys to create an authentication token
region: region,
hostname: dbEndpoint,
port: dbPort,
username: dbUsername
}, function(err, token) {
if (err) {
console.log(`could not get auth token: ${err}`);
cb(err);
} else {
var connection = mysql.createConnection({
host: dbEndpoint,
port: dbPort,
user: dbUsername,
password: token,
database: dbName,
ssl: 'Amazon RDS',
authSwitchHandler: function (data, cb) { // modifies the authentication handler
if (data.pluginName === 'mysql_clear_password') { // authentication token is sent in clear text but connection uses SSL encryption
cb(null, Buffer.from(token + '\0'));
}
}
});
connection.connect();
// TODO replace with your SQL query
connection.query('SELECT * FROM lambda_test.test', function (err, results, fields) {
connection.end();
if (err) {
console.log(`could not execute query: ${err}`);
cb(err);
} else {
cb(undefined, results);
}
});
}
});
};
Instead of using mysql.createConnection() and use your RDS Signer token:
var sequelize = require('sequelize')
const Sequelize = new sequelize(
process.env.database_name,
process.env.databse_user,
token,
{
dialect: 'mysql',
dialectOptions: {
ssl: 'Amazon RDS',
authPlugins: { // authSwitchHandler is deprecated
mysql_clear_password: () => () => {
return token
}
}
},
host: process.env.db_proxy_endpoint,
port: process.env.db_port,
pool: {
min: 0, //default
max: 5, // default
idle: 3600000
},
define: {
charset: 'utf8mb4'
}
}
// then return your models (defined in separate files usually)
await Sequelize.authenticate() // this just does a SELECT 1+1 as result;
await Sequelize.sync() // DO NOT use this in production, this tries to create tables defined by your models. Consider using sequelize migrations instead of using sync()
Also it's a good idea to keep your database connection parameters in a config file so no one can see them. (process.env)
We are working with Sequelize and Lambda, but you will need to reserve more resources, in our case we need at least 1GB to run a lambda with Sequelize. Without it, just with mysql2 it runs just with 128MB.
But if you really wanna use Sequelize just replace your createConnection for something like what you will find in sequelize doc
Probably you will use the context.callbackWaitsForEmptyEventLoop=true because you may have some issues when you call the callback function and you get nothing because your Event Loop probably will never be empty.

Why is testing a sequelize connection to MySQL causing timeout?

New to node and making a generic express application that connects to MySQL db using sequelize. Doing some unit tests on the db connection with jasmine-node and I keep getting timeouts when i try to connect with sequelize.
// Test the MySQL connection
describe("MySQL", function() {
it("is connectable", function(next) {
var mysql = require('mysql');
var dbconfig = require('../config/database');
var connection = mysql.createConnection(dbconfig.connection);
connection.connect(
function(err, db) {
expect(err).toBe(null);
connection.end();
next();
}
);
});
it("is connectable using sequelize", function(next){
var dbconfig = require('../config/database');
var Sequelize = require('sequelize');
var sequelize = new Sequelize(dbconfig.connection.database, dbconfig.connection.user, null,
function(err, db){
expect(err).toBe(null);
sequelize.close();
next();
}
);
});
});
Of the two tests above, the first passes fine, but the test for sequelize times out. Here is the what I get on the console.
Failures:
1) MySQL is connectable using sequelize
Message:
timeout: timed out after 5000 msec waiting for spec to complete
Stacktrace:
undefined
Finished in 6.267 seconds
Here is the database config file.
// config/database.js
module.exports = {
'connection': {
'dialect': 'mysql',
'user': 'root',
'password': '',
'host': 'localhost',
'port' : '3306',
'database': 'my_node_db'
}
};