I'm trying to create a database connection structure that allow multi database connections but I'm having problems about saving the connection so I can use in mssql.request().
I login form the user has to choose which database wants to use, so I'm thinking in trigger the select box database with this code that works fine.
LoginController.js
setDB: (req, res) =>
{
var connection = db.setDB(req.params.dbname);
connection.then(result => {
res.send(result);
});
},
db.setDB
const mssql = require('mssql');
module.exports =
{
setDB: (req, res) =>
{
console.log('Prepare to connect to ' + req);
return new Promise(function (resolve, reject){
var result = makeConnection(req);
result.then(value => {
console.log('result: ' + value);
if(value == 0)
{
console.log('Unknown database!');
resolve('Unknown database!');
}
else if(value == 1)
{
console.log('Error trying to connect! Maybe wrong connection data.');
resolve('Error trying to connect! Maybe wrong connection data.');
}
else if(value == 2)
{
console.log('Connection Done!');
resolve('Connection Done!');
}
}).catch(err => {
console.log(err);
console.log('Error handle setDB() results.');
reject('Error handle setDB() results! Call tech guy.');
});
})
//return connection;
}
}
function makeConnection(dbname)
{
return new Promise(function (resolve, reject){
console.log('Start connection....');
const configs = {
Emp1: {
user: "us",
password: "pass",
server: "ip",
database: "Emp1",
pool: {
max: 20,
min: 0,
idleTimeoutMillis: 900000
}
},
Emp2: {
user: "us",
password: "pass",
server: "ip",
database: "Emp2",
pool: {
max: 20,
min: 0,
idleTimeoutMillis: 900000
}
}
};
var config = configs[dbname];
if(config == undefined)
{
resolve(0);
}
global.conn = new mssql.Connection(config);
conn.connect(function(err)
{
if (err) {
console.log(err);
resolve(1);
} else {
console.log('Database Connected!');
resolve(2);
}
});
});
}
I do this global.conn = new mssql.Connection(config); to try to save the connection.
Now if I try to access a link(index) that do a query I have error because conn is not defined ...
var db = require('../config/db');
var mssql = require('mssql');
var squel = require("squel");
var request = new mssql.Request(conn);
module.exports =
{
index: (req, res) => {
console.log("User Index");
request.query("SELECT * from us",(err, records) => {
console.log(err);
//console.log(records);
res.send(records[0].username);
});
}
}
I appreciate a lot your opinion about the better way to do this, I don't see much information about multi database connection.
The user has to choose database in login form but after I have to save the database name but how? I already think in cache... I don't know, I need really some advices.
Any doubt about that ask me please.
Thank you
Related
I tried to connect my Dialogflow agent with MySQL DB at my GCP, but it didn't work well.
I just wanna see the results in console, but there's no results about that.
I can only see the result "Undefined", but since I am not familiar with Node.js, I am not sure what this means.
Since there is no content in the result, I cannot proceed to the next step.
Here is my index.js script :
// See https://github.com/dialogflow/dialogflow-fulfillment-nodejs
// for Dialogflow fulfillment library docs, samples, and to report issues
'use strict';
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
const mysql = require('mysql');
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
function welcome(agent) {
agent.add(`Welcome to my agent!`);
}
function fallback(agent) {
agent.add(`I didn't understand`);
agent.add(`I'm sorry, can you try again?`);
}
function connectToDatabase() {
const connection = mysql.createConnection({
host: '34.64.***.***',
user: 'username',
password: 'password',
database: 'dbname'
});
return new Promise((resolve,reject) => {
connection.connect();
console.log('connection successed.');
resolve(connection);
});
}
function queryDatabase(connection, name){
return new Promise((resolve, reject) => {
connection.query('SELECT * FROM tb_user WHERE name = ?', name, (error, results, fields) => {
console.log('query successed.');
resolve(results);
});
});
}
function queryDatabase2(connection){
return new Promise((resolve, reject) => {
connection.query('SELECT * FROM tb_user', (error, results, fields) => {
if (error) console.log(error);
console.log('results', results);
});
});
}
function handleReadFromMysql(agent) {
const user_name = agent.parameters.name;
console.log(user_name.name);
return connectToDatabase()
.then(connection => {
console.log('connectToDatabase passed');
return queryDatabase(connection, user_name.name)
//return queryDatabase2(connection)
.then(result => {
console.log('queryDatabase passed');
console.log(result);
agent.add(`User name is ${user_name} .`);
//result.map(user => {
//if(user_name === user.name) {
//agent.add(`UserID is ${user.id}`);
//}
//});
connection.end();
});
});
}
let intentMap = new Map();
intentMap.set('Default Welcome Intent', welcome);
intentMap.set('Default Fallback Intent', fallback);
intentMap.set('findName', handleReadFromMysql);
agent.handleRequest(intentMap);
});
and the logs are :
enter image description here
Please somebody help me...
I solved this problem 4 months ago, so I share my code to help another like me.
I use socketPath of DB info. I forgot the reason.
function connectToDatabase() {
const connection = mysql.createConnection({
socketPath: '/cloudsql/*************:asia-northeast3:****',
user: '****',
password: '****',
database: '****'
});
return new Promise((resolve, reject) => {
connection.connect();
console.log('connection successed.');
resolve(connection);
});
}
And make query function like :
function findNameCountQuery(connection, name) {
return new Promise((resolve, reject) => {
var sql = `SELECT * FROM tb_user WHERE name = ?`;
var execSql = connection.query(sql, [name], (error, results) => {
if (error) throw error;
resolve(results);
});
});
Then I use agent function like :
async function findName(agent) {
const user_name = agent.parameters.person.name;
const connection = await connectToDatabase();
const result = await findNameQuery(connection, user_name);
result.map(user => {
message += `사용자 ID seq number : ${user.seq}\n`;
});
agent.add(message);
connection.end();
}
Hope to be helpful.
I have a nodejs project with the current structure below, I need to insert a registry on clients table and return the last inserted ID from this table so I can use it in a second table, but I need to wait until the insert is completed in clients table, before insert the client ID on my second table. I'm trying to use async/await, but I'm always getting a null value.
My MYSQL connection: db.model.js
const config = require('config');
const mysql = require("mysql");
const connection = mysql.createConnection({
host: config.get('mysql.host'),
user: config.get('mysql.user'),
password: config.get('mysql.password'),
database: config.get('mysql.database')
});
connection.connect(function (err) {
if (err) {
console.error(`MySQL Connection Error: ${err.stack}`);
return;
}
console.log(`MySQL connected successfully!`);
});
module.exports = connection;
My CLIENT model
const mysql = require("./db.model");
const Client = function(client) {
this.login = client.login;
};
Client.create = (newClient, result) => {
mysql.query("INSERT INTO clients SET ?", newClient,
(err, res) => {
if (err) {
console.log("error: ", err);
result(err, null);
return;
}
result(null, {
id: res.insertId,
...newClient
});
}
);
};
module.exports = Client;
this is the client controller (i'm trying to use async/await here)
const Client = require('../models/client.model');
exports.create = (login) => {
const client = new Client({
login: login
});
Client.create(client, async (err, data) => {
if(!err) {
return await data.id;
} else {
return false;
}
});
}
And this is another controller, where I want to use methods from my client controller:
const ClientController = require('../controllers/client.controller');
...
utils.connect()
.then(clt => clt.sub.create(data))
.then((sub) => {
let lastInsertedId = ClientController.create(sub.login);
// lastInsertedId always return null here,
// but I know ClientController return a value after some time.
// method below will fail because lastInsertedId cannot be null
TransactionController.transactionCreate(lastInsertedId,
sub.id,
sub.param);
})
.catch(error => res.send(error.response.errors))
any help appreciated.
File to create database connection
const config = require('config');
const mysql = require('mysql2');
const bluebird = require('bluebird');
const dbConf = {
host: config.dbhost,
user: config.dbuser,
password: config.dbpassword,
database: config.database,
Promise: bluebird
};
class Database {
static async getDBConnection() {
try {
if (!this.db) {
// to test if credentials are correct
await mysql.createConnection(dbConf);
const pool = mysql.createPool(dbConf);
// now get a Promise wrapped instance of that pool
const promisePool = pool.promise();
this.db = promisePool;
}
return this.db;
} catch (err) {
console.log('Error in database connection');
console.log(err.errro || err);
}
}
}
module.exports = Database;
Use connection to execute your native query
const database = require('./database');
let query = 'select * from users';
let conn = await dl.getDBConnection();
let [data, fields] = await conn.query(query);
So I'm still using only the npm mysql package, but now I transformed all my queries into promises like below, so I can just wait until all the queries are completed.
const create = (idCliente, transactionId, amount, status) => {
const sql = "INSERT INTO transactions SET ?";
const params = {
id_cliente: idCliente,
transaction_id: transactionId,
amount: amount,
status: status
};
return new Promise((resolve, reject) => {
pool.query(sql, params, (err, result) => {
if (err) {
return reject(err);
}
resolve(result);
});
});
};
then I use like this:
create(params)
.then((result) => {
//call more queries here if needed
})
.catch((err) => { });
You can use sync-sql package of npm for execute async queries.
https://www.npmjs.com/package/sync-sql
Here is an example of it:
const express = require('express')
const mysql = require('mysql')
const app = express()
var syncSql = require('sync-sql');
// Create Connection
const connect = {
host: 'localhost',
user: 'root',
password: '',
database: 'ddd_test'
}
const db = mysql.createConnection(connect)
db.connect((err) => {
if (err) {
throw err
}
console.log("Connected");
})
function getDbData(query) {
return syncSql.mysql(connect, query).data.rows
}
app.get("/getData", async (req, res, next) => {
let sql = 'SELECT * from registration';
res.json({
data:getDbData(sql)
});
})
app.listen(3000, () => {
console.log('App listening on port 3000!');
});
I just wanted to be so clear as I can, So I have an MS SQL nodejs API, through which I interact with my android and Desktop Application. Currently its working fine, but it is not on pool connection. I think that is why when more people use my app it just doesn't give the response and gives an error more LIKE
Connection already exists close SQL.close() first
So I was planning on upgrading my API to pool connection, by which means more people can connect to my API simultaneously. Right?
So I have this connection to the DB code that has the connection and query look like this :
Connection var dbConfig = {
user: 'sa',
password: "pmis13",
server: '19',
database: 'CUBES_HO',
};
Query handler :
function executeQuery(query) {
return new Promise((resolve, reject) => {
sql.connect(dbConfig, function (err) {
if (err) {
reject(err);
sql.close();
} else {
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query(query, function (err, data) {
if (err) {
reject(err);
sql.close();
} else {
resolve(data);
sql.close();
}
});
}
});
});}
And the query look like this :
app.get("/dailysale/:date", function (req, res) {
var query = "SELECT SUM(bill_amt) AS totalSale FROM [CUBES_HO].[dbo].[vw_bill_summary] where inv_loc_key = 2 and bill_sale_date = '"+req.params.date+"'";
executeQuery(query)
.then((data) => {
res.status(200).send({ "msg": "Records fetched", "data": data.recordsets });
}).catch((err) => {
res.status(500).json({ "msg": err.message });
});});
I want to convert this or we can say upgrade this api to pool connection, which sounds more reliable for multiple connection. Correct me I am wrong.
I couldn't put this link in the comments section so posting it here. This answer on SO explains difference between mysql.createConnection and mysql.createPool.
An example to help you create pool connection
const pool = new sql.ConnectionPool({
user: '...',
password: '...',
server: 'localhost',
database: '...'
})
Found it here.
I found a work arround by doing this
var config ={
user: 'sa',
password: "pdt09",
server: '3',
database: 'CUBES',
options: {encrypt: true}
};
async function executeQuery(sqlquery) {
return new Promise(function(resolve, reject) {
(async() => {
const pool = new sql.ConnectionPool(config);
pool.on('error', err => {
// ... error handler
console.log('sql errors', err);
});
try {
await pool.connect();
let data = await pool.request().query(sqlquery);
resolve(data);
} catch (err) {
reject(err)
} finally {
pool.close(); //closing connection after request is finished.
}
})();
}).catch(function(err) {
});
}
and the worker will remain the same
I need to configure the knexfile.js using the secrets retrieve from the secret manager.
I retrieve the secrets from secret manager and stores it in secret variable and use it in configuration.
var AWS = require('aws-sdk'),
endpoint = "abcd",
region = "us-east-1",
secretName = "abcd",
secret,
binarySecretData;
var client = new AWS.SecretsManager({
endpoint: endpoint,
region: region
});
client.getSecretValue({
SecretId: secretName
}, function (err, data) {
if (err) {
if (err.code === 'ResourceNotFoundException')
console.log("The requested secret " + secretName + " was not found");
else if (err.code === 'InvalidRequestException')
console.log("The request was invalid due to: " + err.message);
else if (err.code === 'InvalidParameterException')
console.log("The request had invalid params: " + err.message);
} else {
if (data.SecretString !== "") {
secret = data.SecretString;
} else {
binarySecretData = data.SecretBinary;
}
}
});
module.exports = {
development: {
client: secret.localClient,
connection: {
host: secret.localHost,
user: secret.localUser,
password: secret.localPassword,
database: secret.localDatabase,
charset: "utf8"
}
},
};
But it shows an error
TypeError: Cannot read property 'localClient' of undefined
This is now possible in Knex. You can pass an async function to the configuration.
async function getConfig() {
return new Promise((resolve, reject) => {
client.getSecretValue({ SecretId: 'SECRETID' }, function(
err,
data
) {
if (err) {
console.log('secretsErr', err);
reject(err);
} else {
console.log('Secrets Manager call successful');
if ('SecretString' in data) {
let secret = data.SecretString;
secret = JSON.parse(secret);
const config = {
user: secret.DbUser,
password: secret.DbPassword,
server: secret.DbServer,
database: secret.DbDatabase,
expirationChecker: () => false,
options: {
encrypt: true,
enableArithAbort: true
}
};
resolve(config);
} else {
console.log('no secret found');
reject();
}
}
});
}
let knex = require('knex')({
client: 'mssql',
connection: async function() {
return await getConfig();
}
});
Getting secret is asynchronous operation, so your variable secret it doesn't exist yet when you are trying to export it from knexfile.js.
You probably should first fetch secret to be stored somewhere locally, when starting up virtual machine and then in knexfile.js read it synchronously for example from local file.
I have problem with my node.js bot to roulette. Bot is fully set up but when I launching it, it gives me error "Bot stopped with code null". Can someone help me to fix it?
Here is the error screenshot: http://i.imgur.com/zfZoMD4.png
Code:
function login(err, sessionID, cookies, steamguard) {
if(err) {
logger.error('Auth error');
logger.debug(err);
if(err.message == "SteamGuardMobile") {
account.twoFactorCode = SteamTotp.generateAuthCode(account.shared_secret);
logger.warn('Error in auth: '+account.twoFactorCode);
setTimeout(function() {
community.login(account, login);
}, 5000);
return;
}
process.exit(0);
}
logger.trace('Sucesfully auth');
account.sessionID = sessionID;
account.cookies = cookies;
community.getWebApiKey('csgobananas.com', webApiKey);
community.startConfirmationChecker(10000, account.identity_secret);
}
function webApiKey(err, key) {
if(err) {
logger.error('Cant make apikey')
logger.debug(err);
process.exit(0);
return;
}
account.key = key;
logger.trace('API key bot '+account.accountName+' '+account.key);
offersSetup();
community.loggedIn(checkLoggedIn);
}
function offersSetup() {
logger.trace('Loaded steam-tradeoffers');
offers.setup({
sessionID: account.sessionID,
webCookie: account.cookies,
APIKey: account.key
});
}
function checkLoggedIn(err, loggedIn, familyView) {
if((err) || (!loggedIn)) {
logger.error('We arent logged in')
process.exit(0);
} else {
logger.trace('Logged in');
account.auth = true;
bot_manager.js code:
var forever = require('forever-monitor');
var mysql = require('mysql');
var pool = mysql.createPool({
connectionLimit : 10,
database: 'placeholder',
host: 'placeholder',
user: 'placeholder',
password: 'placeholder'
});
query('SELECT * FROM `bots`', function(err, row) {
if((err) || (!row.length)) {
console.log('Failed request or empty bot table');
console.log(err);
return process.exit(0);
}
console.log('List of bots:');
row.forEach(function(itm) {
console.log('Launching bot# '+itm.id);
var bot = new (forever.Monitor)('bot.js', {
args: [itm.id]
});
bot.on('start', function(process, data) {
console.log('Bot with ID '+itm.id+' started');
});
bot.on('exit:code', function(code) {
console.log('Bot stopped with code '+code);
});
bot.on('stdout', function(data) {
console.log(data);
});
bot.start();
});
});
function query(sql, callback) {
if (typeof callback === 'undefined') {
callback = function() {};
}
pool.getConnection(function(err, connection) {
if(err) return callback(err);
console.info('Database connection ID: '+connection.threadId);
connection.query(sql, function(err, rows) {
if(err) return callback(err);
connection.release();
return callback(null, rows);
});
});
}