Dynamically change the name of mySql database in pool in node.js - mysql

connection.js
var mysql = require("mysql");
const { createPool } = require("mysql");
const pool = createPool({
port: process.env.DB_PORT,
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.MYSQL_DB,
connectionLimit: 10,
});
module.exports = pool;
product.service.js
const pool = require("../../../config/database");
module.exports = {
viewVariate: (callBack) => {
pool.query(
`SELECT varId , varName FROM variations WHERE varIsActive='1'`,
(errors, results, fields) => {
if (errors) {
return callBack(errors);
}
return callBack(null, results);
}
);
},
}
I have to maintain more than 100 users. so each person has own database in that node app. each person database name call via API , so I need to set given database name to above pool dynamically , I referred may ways. it did not work. connection.js file is my database connection with pool. then it call to service files to make connection queries. for that pool data obtains form env file. it doesn't matter when config mentioned requirement will be done.

Related

pool.querty is not a function. Trying to connect google-cloud mysql instance from local machine

When trying to connect to the mysql instance on gcloud using nodejs and express. I'm getting the error "pool.query" is not a function. Bear with me since this the first time using gcloud and nodejs, i may be missing something obvious. I have already authorized my local ip,
This is my config
const config = {
user: process.env.DB_USER, // e.g. 'my-db-user'
password: process.env.DB_PASS, // e.g. 'my-db-password'
database: process.env.DB_NAME, // e.g. 'my-database'
socketPath: '/cloudsql/'+ process.env.INSTANCE_UNIX_SOCKET, // e.g. '/cloudsql/project:region:instance'
connectionLimit: 5,
connectTimeout: 10000, // 10 seconds
waitForConnections: true, // Default: true
queueLimit: 0, // Default: 0
};
module.exports = config;
This is my pool creation method
//dotenv
require('dotenv').config();
// import mysql2
const mysql = require('mysql2/promise');
// get config
const config = require("./config");
// Connect to database
// createUnixSocketPool initializes a Unix socket connection pool for
// a Cloud SQL instance of MySQL.
async function createUnixSocketPool() {
return mysql.createPool({...config,});
};
module.exports = {createUnixSocketPool};
And lastly my code for connecting
const path = require('path');
const express = require('express');
const { createUnixSocketPool } = require("./db");
const app = express();
// create mysql pool
const pool = createUnixSocketPool();
app.get('/',async (req,res) => {
console.log(await pool.query("show tables;"));
res.send("test");
});
// Listening
const PORT = process.env.PORT || 3000
app.listen(PORT, () => console.log('App is listening on port '+ PORT));
For some reason this says that pool.query doesn't exist? I'm very new to node.js and javascript in general, what am i missing?

Query a Google cloud SQL instance in Node.js from a GKE pod with cloud sql proxy running as sidecar

I am tasked with adding a MySql database to a microservice application for work. I am the only person on this task and don't really have anyone to turn too for advice so I am reaching out to the internets for help. I have succesfully deployed a pod that is running a small test application and the cloud-sql-proxy. I have scoured the documentation trying to figure out how to connect to the db and perform a query and this is what I have come up with (but it doesn't work).
const express = require('express');
const mysql = require('mysql');
const bodyParser = require('body-parser')
const cors = require('cors');
const axios = require('axios');
const app = express();
app.use(bodyParser.json());
app.use(cors())
app.enable('trust proxy');
// Automatically parse request body as form data.
app.use(express.urlencoded({extended: false}));
// This middleware is available in Express v4.16.0 onwards
app.use(express.json());
// [START cloud_sql_mysql_mysql_create_tcp]
const createTcpPool = async config => {
// Extract host and port from socket address
const dbSocketAddr = process.env.DB_HOST.split(':');
// Establish a connection to the database
return mysql.createPool({
user: process.env.DB_USER, // e.g. 'my-db-user'
password: process.env.DB_PASS, // e.g. 'my-db-password'
database: process.env.DB_NAME, // e.g. 'my-database'
host: dbSocketAddr[0], // e.g. '127.0.0.1'
port: dbSocketAddr[1], // e.g. '3306'
// ... Specify additional properties here.
...config,
});
};
// [END cloud_sql_mysql_mysql_create_tcp]
var pool = createTcpPool();
const stuff = pool.query('SELECT * FROM entries');
function getQuery() {
console.log(stuff);
}
getQuery()
Here is a picture of the error I get when I deploy the pod and the logs from the proxy to verify it's running
I'm pretty new to MySql and GKE and trying to figure this out has been a huge struggle. I just want to know how I can actually query the db and would greatly appreciate some assistance or code sample to point me in the right direction, thanks internets.
As mentioned in the thread1 ,
Handling such functions can be done through following example :
const mysql = require('mysql');
const pool = mysql.createPool({ connectionLimit : 1, socketPath: '/cloudsql/' + '$PROJECT_ID:$REGION:$SPANNER_INSTANCE_NAME',
user: '$USER', p
assword: '$PASS',
database: '$DATABASE' });
exports.handler = function handler(req, res)
{ //using pool instead of creating connection with function call
pool.query(`SELECT * FROM table where id = ?`,
req.body.id, function (e, results) {
//made reply here
}); };
For more information you can refer to the documentation related to TCP connection when using Node js.
const createTcpPool = async config => {
// Extract host and port from socket address
const dbSocketAddr = process.env.DB_HOST.split(':');
// Establish a connection to the database
return mysql.createPool({
user: process.env.DB_USER, // e.g. 'my-db-user'
password: process.env.DB_PASS, // e.g. 'my-db-password'
database: process.env.DB_NAME, // e.g. 'my-database'
host: dbSocketAddr[0], // e.g. '127.0.0.1'
port: dbSocketAddr[1], // e.g. '3306'
// ... Specify additional properties here.
...config,
});
};
So trying to create a pool by calling createTcpPool seems to have been the issue. I changed it to
let pool = mysql.createPool({
user: process.env.DB_USER, // e.g. 'my-db-user'
password: process.env.DB_PASS, // e.g. 'my-db-password'
database: process.env.DB_NAME, // e.g. 'my-database'
host: '127.0.0.1', // e.g. '127.0.0.1'
port: '3306'
});
and got a succesful return from my db.

errno: 1203, code: 'ER_TOO_MANY_USER_CONNECTIONS' in nodejs mysql code?

Hello Everyone,
I'm a beginner in Node.js Mysql. I have connected to Node.js with mysql. While starting the Node.js server, I got the error like " code: 'ER_TOO_MANY_USER_CONNECTIONS', " further I will attach the mysql db connection code below. Any type of help would be appreciated. Thanks in advance...
var db = mysql.createPool({
host: 'xxxxxxxxxxxxxxxxx',
port: 'xxx',
user: 'xxxx',
password: 'xxx',
database: 'xxx'
});
db.getConnection((err, tempConn) => {
if (err) {
console.log(err);
}
else {
tempConn.release();
console.log('Mysql Connected');
}
});
module.exports={db};
If you're creating a pool you don't need to use getConnection. There is a shortcut that allows you to use it directly. If you do use getConnection you must follow it with a query, then you may release the connection. Your example is missing a query.
Here is a helpful template for using a pool config:
// in your application initialization file such as app.js
//
// other require items here as well like express maybe?
//
const mysql = require('mysql');
const connection = mysql.createPool({
connectionLimit: 10,
host: process.env.DB_HOST || '127.0.0.1',
user: process.env.DB_USER || 'local_user',
password: process.env.DB_PASSWORD || 'local_password',
database: process.env.DB_NAME || 'local_database',
multipleStatements: true,
charset: 'utf8mb4' // necessary if you might need support for emoji characters
});
connection.on('connection', function (connection) {
// handy for testing
console.log('Pool id %d connected', connection.threadId);
});
connection.on('enqueue', function () {
// handy for testing
console.log('Waiting for available connection slot');
});
global.db = connection;
//
// other app setup stuff here like app.set, app.engine, app.use, module.exports = app and all that good stuff
//
// later…
// everywhere else in your app, use the global db variable when running queries
// ../new_users.js or similar maybe?
const _create_user = (user_payload) => {
db.query(
'INSERT INTO users SET ?', user_payload, function(error, results, fields) {
if (error) throw error;
console.log(results);
});
}
// maybe we are in a module that has access to
// the request object so we can use something
// that has come via POST
//
// here is a manual object as a placeholder…
let new_user = {
first_name: 'John',
last_name: 'Smith',
email: 'j.smith#example.com',
password: 'keyboard_cat'
}
_create_user(new_user);

mvc with node/express and mysql

I'm getting confused. All the tutorials I see with mySql end up with something like this:
in models/dbconnection.js
var mysql = require('mysql');
port = process.env.PORT || 3333;
if (port == 3333) {
var connection = mysql.createConnection({
host: 'localhost',
port: 3306,
user: 'root',
password: 'root',
database: 'nameDataBase',
insecureAuth: true
});
} else {
console.log("Error");
}
connection.connect();
module.exports = connection;
And then in routes/user.js
...
router.delete("/:id", verifyToken, (req, res) => {
const newLocal = "DELETE FROM login_user WHERE id = ?";
connection.query(newLocal, [req.params.id], (err,rows,fields) => {
if (err) {
res.sendStatus(500);
return;
}
console.log(rows.affectedRows);
res.status(200).send({delete: rows});
});
});
module.exports = router;
model and controller aren't getting mixed here? If tomorrow I want to change the type of database, I have to make changes in the model and in the routes. Shouldn't I make functions such as getAllUsersBlaBla(params) in something like models/user.js and then call it from routes/user.js ?
I agree. There shouldn't be any database queries in the router, which is considered part of the controller in MVC.
The model should provide wrapper functions around database queries that can be called from the controller.
A lot of node apps (and probably tutorials) will choose simplicity rather than modularity, that's why you would see code like that.

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.