Reusing SQL server Database Connections With Azure Functions Using Javascript - javascript

I cannot find clear information on how to manage SQL server database connections from an Azure function written in Javascript.
I am using a connection pool code -
const pool = new sql.ConnectionPool(config);
const poolConnect = pool.connect();
pool.on('error', err => {
// ... error handler
})
and I am using the poolConnect object from the function which is executing the query
export const selectQuery = function() {
const connectionPool = await mssqlDBPoolConnect;
const request = connectionPool.request();
await request.query('select query');
}
So how can I use the same connection pool across all azure functions.

Create two folder named config and toolkit under your root path. Put your db.js in config folder, and create a sql helper class to export a function named sqltools.js in toolkit folder.
So you could use the same connection pool by calling sqltools in your function's code. This step help you to reduce using the same code in every function.
Try use the db.js code below:
const sql = require('mssql')
const config = {
user: 'yourusername',
password: 'yourpassword',
server: 'yoursqlserver.database.windows.net', // You can use 'localhost\\instance' to connect to named instance. Do not use TCP.
database: 'yourdb',
"options": {
"encrypt": true,
"enableArithAbort": true
}
}
const poolPromise = new sql.ConnectionPool(config)
.connect()
.then(pool => {
console.log('Connected to MSSQL')
return pool
})
.catch(err => console.log('Database Connection Failed! Bad Config: ', err))
module.exports = {
sql, poolPromise
}
The sqltools.js class:
const { poolPromise } = require('../config/db')
module.exports.sqltools = {
ExecSqlQuery : async function(arg){
const pool = await poolPromise
//SELECT *FROM SYSOBJECTS WHERE xtype = \'U\'
var result=null;
try {
result = await pool.request()
.query(arg)
} catch (error) {
console.log(error.message);
}
return result;
},
ExecProce : function (arg2, arg3, arg4){
console.log(arg2,arg3,arg4);
}
}
Here is my HttpTrigger1 index.js code, call ExecSqlQuery to exec sqlstrings:
const { sqltools } = require('../toolkit/sqltools');
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
var result=null;
try {
// call ExecSqlQuery func
result = await sqltools.ExecSqlQuery('SELECT *FROM SYSOBJECTS WHERE xtype = \'U\'');
} catch (error) {
console.log(error.message);
}
const responseMessage ="Func 1 Result : TableName= " + result.recordset[0].name;
context.res = {
// status: 200, /* Defaults to 200 */
body: responseMessage
};
}

Related

Mongoose data Writing issue in Javascript

Just started with a javascript couple of days back. I am trying to use MongoDB with mongoose to write the data but it is not writing even though the connection is established.
I would really appreciate it if you can help me point out what I am missing here.
dbtest.js - module to create connection
require("dotenv").config();
const mongoose = require("mongoose");
const Block = require("./model/blockSchema");
const connectDB = async () => {
try {
await mongoose.connect(process.env.DATABASE_URI, {
useUnifiedTopology: true,
useNewUrlParser: true,
});
console.log("CONNECTED to MONGODB DATABASE");
} catch (err) {
console.error(err);
}
};
module.exports = connectDB;
blockchain.js
Even though I have verified the connection before calling the main method, it looks like the connection is not available to class methods.
require("dotenv").config();
const { hash256 } = require("../util/util");
const block = require("./block");
const blockchain = require("./blockHeader");
const Block = require("../database/model/blockSchema");
const { mongoose } = require("mongoose");
const connect = require("../database/dbtest");
VERSION = 1;
const ZERO_HASH = String("0").padStart(64, "0");
// Create connection
connect();
class Blockchain {
GenesisBlock() {
try {
const BlockHeight = 0;
const prevBlockHash = ZERO_HASH;
this.addBlock(BlockHeight, prevBlockHash);
} catch (err) {
console.log(`Error in Genesis Blockchain Function \n ${err}`);
}
}
addBlock(BlockHeight, prevBlockHash) {
let timestamp = Date.now();
let Transaction = `Codies Alert sent ${BlockHeight} to Anni`;
let merkleRoot = hash256(Transaction);
let bits = "ffff001f";
let blockHeader = new blockchain.BlockHeader(
VERSION,
prevBlockHash,
merkleRoot,
timestamp,
bits
);
//Mine a Block
blockHeader.mine();
// Create Schema Instance to Write the data
let BlockObj = new Block({
Height: BlockHeight,
BlockSize: 1,
blockHeader: {
version: 1,
prevBlockHash: "00000",
timestamp: timestamp,
bits: bits,
nonce: blockHeader.nonce,
blockHash: blockHeader.blockhash,
},
TxCount: 1,
Transactions: Transaction,
});
// Mongoose Schema, Write data
BlockObj.save((err) => {
if (err) return console.log(`Error while Writing the Block ${err}`);
console.log(`Block Written Successfully!!!!!!!`);
});
this.chain = new block.Block(BlockHeight, 1, blockHeader, 1, Transaction);
console.log(BlockObj);
}
// Main Function to trigger the process
main() {
this.chain = "";
this.GenesisBlock();
while (true) {
let lastBlock = this.chain;
let Blockheight = lastBlock.Height + 1;
let prevBlockHash = lastBlock.BlockHeader.blockhash;
this.addBlock(Blockheight, prevBlockHash);
}
}
}
mongoose.connection.once("open", async () => {
console.log("Connection Verified and ready to write data");
// Create an instance and call the main method
const blockchain = new Blockchain();
blockchain.main();
});
Issue was due to async/await. Here is the updated code that works.
require("dotenv").config();
const { hash256 } = require("../util/util");
const block = require("./block");
const blockchain = require("./blockHeader");
const Block = require("../database/model/blockSchema");
const connect = require("../database/dbtest");
const getLastBlock = require("../database/read");
VERSION = 1;
const ZERO_HASH = String("0").padStart(64, "0");
let mongoose = "";
class Blockchain {
async GenesisBlock() {
try {
console.log(mongoose.connection.readyState);
const BlockHeight = 0;
const prevBlockHash = ZERO_HASH;
await this.addBlock(BlockHeight, prevBlockHash);
} catch (err) {
console.log(`Error in Genesis Blockchain Function \n ${err}`);
}
}
async addBlock(BlockHeight, prevBlockHash) {
let timestamp = Date.now();
let Transaction = `Codies Alert sent ${BlockHeight} to Anni Maan`;
let merkleRoot = hash256(Transaction);
let bits = "ffff001f";
let blockHeader = new blockchain.BlockHeader(
VERSION,
prevBlockHash,
merkleRoot,
timestamp,
bits
);
blockHeader.mine();
let BlockObj = {
Height: BlockHeight,
BlockSize: 1,
blockHeader: {
version: 1,
prevBlockHash: blockHeader.prevBlockhash,
merkleroot: merkleRoot,
timestamp: timestamp,
bits: bits,
nonce: blockHeader.nonce,
blockhash: blockHeader.blockhash,
},
TxCount: 1,
Transactions: Transaction,
};
// Mongoose Schema, Write data
try {
await new Block(BlockObj).save();
console.log(BlockObj);
console.log("Block Written Successfully");
this.chain = new block.Block(BlockHeight, 1, blockHeader, 1, Transaction);
} catch (err) {
console.log(`Error in addBlock Function \n ${err}`);
}
}
// Main Function to trigger the process
async main() {
const lastBlock = await getLastBlock.main(true);
console.log(lastBlock[0]);
this.chain = lastBlock[0];
if (!this.chain) {
await this.GenesisBlock();
}
while (true) {
console.log(mongoose.connection.readyState);
let lastBlock = this.chain;
let Blockheight = lastBlock.Height + 1;
let prevBlockHash = lastBlock.blockHeader.blockhash;
await this.addBlock(Blockheight, prevBlockHash);
}
}
}
const createConnection = async () => {
try {
mongoose = await connect();
const blockchain = new Blockchain();
blockchain.main();
} catch (err) {
console.log("Error while con", err);
}
};
createConnection();
The issue in your code is due to the asynchronous programming, whenever you make a db call it is an asynchronous request and you will need to use async-await or Promises to make it work. In your previous code you haven't used async await thats why your data is not getting written into the db.
You can learn about async await here link and about promises here.
Please go through it, promises are the core concept of js and you will definitely need it if you are using node js.
Also try to learn about synchronous and asynchronous from here, these are really necessary and base of node js.
All these db calls needs to call with promises or async await to make it work.

How to call a javascript function inside another function in node js

I have a file index.js as below. Where I am trying to call a async function getConn in other function createThumbnails. But I am getting the error as "failed to connect to DEDC: 1433 - self signed certificate" in the catch block.
const sharp = require('sharp');
const sql = require('mssql')
// CONNECTION CONFIGURATION OF BASE DB
async function getConn() {
try {
const config = {
user: 'sa_user',
password: '*******',
server: 'DEDC',
database: 'DEMO_BASE'
}
const pool = await new sql.ConnectionPool(config)
const req=await pool.connect()
const conn = await req.request()
return conn;
} catch (err) {
return err;
}
};
const createThumbnails = async() => {
try{
var conn = await getConn();
const query = `exec DBBASE.get_client_info`
var clientusers = await conn.query(query);
} catch (err) {
return err;
}
}
createThumbnails()
How do I exactly call the function getConn inside createThumbnails. Please help. Thanks in advance
It's because you are using variable with the same name as the function.
Try different name:
var conn = await getConn();
const query = `exec DBBASE.get_client_info`
var clientusers = await conn.query(query);
You encounter what called hoisting. Kyle Simpson has a great explaination on this topic
var getConn = await getConn();
which means getConn will be initialized first, before assignment, which equivalents to
var getConn // initialized
getConn = await getConn() // assignment
Then turned out that you got the error
Solution here is to store it in a different variable name, like
var conn = await getConn();
async function getConn() {
return {
query: async () => {
console.log("query called");
},
};
}
const createThumbnails = async () => {
try {
var conn = await getConn();
const query = `exec DBBASE.get_client_info`;
var clientusers = await conn.query(query);
} catch (err) {
console.log(err);
}
};
createThumbnails();
We need to use trustServerCertificate: true in DB configuration i.e in const config

How do I reuse a RabbitMQ connection and channel outside of the "setup structure" with the amqp library?

I am trying to build a simple node.js client using the amqp library, that opens a single connection and then a single channel to a RabbitMQ server. I want to reuse the same connection and channel to send multiple messages. The main problem is, that I don't want to write my entire code inside the callback function of the ceateChannel() function.
How do I reuse the channel outside of the callback function and make sure the callback function has finished before I use the channel?
I've tried both the callback way and the promise way but I can't make either of them work. When using the callback method I run into the described problem.
When using promises, I have the problem that I can't keep a reference of the connection and channel outside of the .then() function because the passed variables get destroyed after setting up the connection and channel.
amqp.connect('amqp://localhost', (err, conn) => {
if (err !== null) return console.warn(err);
console.log('Created connection!');
conn.createChannel((err, ch) => {
if (err !== null) return console.warn(err);
console.log('Created channel!');
//this is where I would need to write the code that uses the variable "ch"
//but I want to move the code outside of this structure, while making sure
//this callback completes before I try using "ch"
});
});
amqp.connect('amqp://localhost').then((conn) => {
return conn.createChannel();
}).then((ch) => {
this.channel = ch;
return ch.assertQueue('', {}).then((ok) => {
return this.queueName = ok.queue;
});
}).catch(console.warn);
why you don't use async\await ?
const conn = await amqp.connect('amqp://localhost');
const ch = await conn.createChannel();
// after that you can use ch anywhere, don't forget to handle exceptions
Also if you use amqplib, don't forget to handle close and internal error events, for example like this:
conn.on('error', function (err) {
console.log('AMQP:Error:', err);
});
conn.on('close', () => {
console.log("AMQP:Closed");
});
Try with a class, like this:
RabbitConnection.js
const amqp = require('amqplib');
const RabbitSettings = {
protocol: 'amqp',
hostname: 'localhost',
port: 5672,
username: 'guest',
password: 'guest',
authMechanism: 'AMQPLAIN',
vhost: '/',
queue: 'test'
}
class RabbitConnection {
constructor() {
RabbitConnection.createConnection();
this.connection = null;
this.channel = null;
}
static getInstance() {
if (!RabbitConnection.instance) {
RabbitConnection.instance = new RabbitConnection();
}
return RabbitConnection.instance;
}
//create connection to rabbitmq
static async createConnection() {
try {
this.connection = await amqp.connect(`${RabbitSettings.protocol}://${RabbitSettings.username}:${RabbitSettings.password}#${RabbitSettings.hostname}:${RabbitSettings.port}${RabbitSettings.vhost}`);
this.channel = await this.connection.createChannel();
this.channel.assertQueue(RabbitSettings.queue);
console.log('Connection to RabbitMQ established');
} catch (error) {
console.log(error);
}
}
//send message to rabbitmq queue
static async sendMessage(message, queueName) {
try {
let msg = await this.channel.sendToQueue(queueName, Buffer.from(message));
console.log('Message sent to RabbitMQ');
return msg;
} catch (error) {
console.log(error);
}
}
}
module.exports = { RabbitConnection };
ServerExpress.js
const express = require('express');
const { RabbitConnection } = require('./RabbitConnection');
const serverUp = () => {
const app = express();
app.get('/', (req, res) => {
RabbitConnection.sendMessage('Hello World', 'test');
res.send('Hello World!');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
};
module.exports = { serverUp };
index.js
const { RabbitConnection } = require("./RabbitConnection");
const { serverUp } = require("./ServerExpress");
serverUp();
RabbitConnection.getInstance();

PostgreSql results printing to console but not displaying in browser

I'm trying to get some data from a pg database to my api endpoint , I can print the results to the console but I can't get them to display in the browser with res.send. I'm guessing the problem is with global and local scope however I've not been able to figure it out. I'm using ES6 but transpiling with babel. Here's a snippet.
app.get('/', (request, response) => {
const { Pool, Client } = require('pg');
const config = {
user: '',
host: '',
database: '',
password: '',
port: ,
}
const pool = new Pool(config);
const client = new Client(config);
let whole = [];
client.connect();
const text = "SELECT * FROM entries where id='1'";
client.query(text)
.then(res => {
console.log(res.rows[0]);
whole.push(res.rows[0]);
})
.catch(e => console.error(e.stack));
response.send(whole);
client.end;
});
This logs to the console
{ id: 1, title: 'First title', body: 'beautiful body' }
However the browser only displays []
This is what babel transpiles it to which is the script I run in node.
var whole = [];
client.connect();
var text = "SELECT * FROM entries where id='1'";
client.query(text).then(function (res) {
console.log(res.rows[0]);
whole.push(res.rows[0]);
}).catch(function (e) {
return console.error(e.stack);
});
response.send(whole);
client.end;
response.send is called outside of the async promise .then resolver, and is therefore executed before you push the row data into the array. Moving response.send into the promise resolver should fix it.
client.query(text).then(res => {
whole.push(res.rows[0]);
client.end();
response.send(whole);
}).catch((e) => {
console.error(e.stack);
});
Alternatively, you can use async/await depending on your babel version and presets/plugins.
const { Client } = require("pg");
const config = {...};
const queryText = "SELECT * FROM entries where id='1'";
app.get("/", async (request, response) => {
const client = new Client(config);
await client.connect();
try {
const queryResponse = await client.query(queryText);
// Send response without pushing to array
response.send(queryResponse.rows[0]);
client.end();
} catch (e) {
console.error(e.stack);
}
});

Hyperledger query never return results

I`m trying to query my business network using buildQuery but it always returns an empty array.
My code is as follows.
This is the connection.js file:
module.exports = {
BusinessNetworkConnection : require('composer-client').BusinessNetworkConnection,
cardName : '',
connection: {},
connect : function() {
var cardType = { type: 'composer-wallet-filesystem' }
this.connection = new this.BusinessNetworkConnection(cardType);
return this.connection.connect(this.cardName);
},
disconnect : function(callback) {
this.connection.disconnect();
}
};
This is my query.js file which being invoked to get results:
const connection = require('./connection');
const getContacts = async (cardName,companyID) => {
connection.cardName = cardName;
try {
await connection.connect();
main();
} catch (error) {
main(error);
}
async function main(error) {
if (error) { return new Error("Ops Error: ",error) };
const statement = 'SELECT org.finance.einvoice.participant.Company WHERE (participantId == _$companyID)'
const query = await connection.connection.buildQuery(statement);
const company = await connection.connection.query(query, { companyID }).catch(err => {return new Error(err)});
await connection.connection.disconnect().catch(err => new Error(err));
console.log(company);
return company;
};
};
module.exports = {
getContacts
};
The expected behavior from getContacts() is to return an asset from business network but it actually returns an empty array.
Current versions: composer-cli 0.20 , composer-playground 0.20 , composer-client 0.20 , composer-common 0.20 and fabric-dev-server 1.2 .
i found the solution for this issue.
i was using card which was not allowed to perform queries. However, when i used the admin card it returned with results.
other way is to allow participants to issue queries in permission.acl file.

Categories

Resources